首页 > 解决方案 > Vue 是什么让开发人员能够在 DOM 元素上使用 class 属性?

问题描述

像 React 这样的 JavaScript 框架和苗条不允许开发人员class在 DOM 元素上使用该属性,因为该class关键字在 JavaScript 中是保留的。同时,像 Vue 这样的其他框架以某种方式解决了这个问题。

Vue 的实现方式是什么让 Vue 开发人员可以class在元素上使用关键字?我想这与 Vue 如何将.vue文件转换为 HTML、CSS 和 JavaScript 有关,但我对细节很好奇。

编辑: Svelte不使用虚拟 DOM,您可以将 class prop 与 Svelte 一起使用。

标签: javascriptreactjsvue.jssvelte

解决方案


tldr; JSX(React 的语言)是 JavaScript 的超集(其中class是保留关键字),而 Vue 和 Svelte 都有模板语言,它们是 HTML 的超集,因此可以class像在 HTML 中一样使用。


在这里为 Svelte 说话。

首先,让我们修正错误的前提:

像 React和 Svelte这样的 JavaScript 框架不允许开发人员在虚拟 DOM 元素上使用 class 属性,因为 class 关键字在 JavaScript 中是保留的。

Svelte 确实允许class在元素和组件上使用关键字。您只需要在适用的限制范围内工作。我们回到这个话题。

让我们从 React 开始。嗯,实际上是 JSX。JSX 是 JS 的严格超集。让我们参考这个很好的解释。JSX 在语法上(任何 JS 程序都是有效的 JSX)语义上(任何 JS 程序在解释为 JSX 时的行为都相同)都是 JS 的超集。

为了做到这一点,JSX 必须尊重 JS 的每一个约束,其中“类是保留关键字”。这就是 React 不允许class关键字的原因。

请注意,这不是技术限制。React可以重新解释class关键字并使其在 JSX 中工作。但这会使 JSX 严格来说不是 JS 的超集。为什么?因为那样的话,在某些情况下,相同的 JS 代码在解释为纯 JS 或 JSX 时的行为会有所不同(即,有一个名为的变量class 必须崩溃才能成为 JS)。

这是一个哲学约束。在某一时刻,JSX 开发人员必须权衡不能使用class关键字的不便与突然不是 JS 的严格超集。一方面,你获得了一点好处,另一方面,你突然从数学上的纯超集降级为“另一种随机模板语言”。

很容易感受到来自 React 的强烈数学倾向,它强调纯函数、“作为状态的函数的视图”、单向数据流等。这实际上是对 React 的一个非常重要的借鉴。他们将数学的许多好处引入日常应用程序开发中。因此,很容易理解(对我来说),这群开发人员更喜欢(喜欢)纯粹性而不是次要的便利。

作为 JS 的超集确实带来了许多优势。即使你对 JSX 一无所知,你也可以利用现有的 JS 知识立即编写一些。只要您不开始使用 JSX 额外功能,您就可以预测代码的所有行为,因为一切都会表现相同。

现在,对于 Svelte 的细节...... Svelte 不使用JSX(据我所知,在大多数情况下也没有使用 Vue)。他们使用自己的模板语言。不确定 Vue,但对于 Svelte,它是一个超集,不是 JS,而是 HTML。Svelte 的创建者 Rich Harris 曾在一次演讲中称其为 HTMLX(不确定这个术语目前有多正式)。就个人而言,这是我对 Svelte 如此满意的主要原因之一。我发现编写 HTML 是 JS 很麻烦,而编写看起来自然的 HTML(X) 到最后,生成 HTML 感觉只是......自然!但我离题了...

所以,问题是 Svelte 也必须在自己选择的法律范围内发挥作用。其中有两个与手头的问题有关。两者都有意义,并且都可以解决。

但首先,为了消除任何误解,Svelte 确实允许class对原生元素使用关键字(与 Svelte 组件相反):

<div class="whatever">No problem with that</div>

如果不是这样,它就不是 HTML 的正确超集。

在这种情况下,class实际上是一个“指令”,这意味着与纯 HTML 类相比,它增加了功能。例如:

<script>
  let blue = true
</script>

<!-- will render as: <div class="blue"></div> -->
<div class:blue />

<!-- will render as: <div class="red"></div> -->
<div class:red={blue} />

<!-- you can have several of them too... -->
<div class="foo" class:red class:blue />

所以 Svelte 允许使用class关键字,这是毫无疑问的。对于本机元素。

现在,对于组件,情况有所不同。这是我之前提到的两条定律。

第一个是 Svelte 组件不强制使用单个根元素。或者任何元素,就此而言。

<script>
  console.log('I am a valid Svelte component with no elements')
</script>
<!-- no code omitted -->
<p>I am a valid Svelte component</p>
<p>Too.</p>

这样做的结果是 Svelte 无法确定它应该自动将class集合应用于包含组件的哪些元素。因此,在这种情况下,它什么也做不了。它会将控制权交还给您。

这并不意味着如果你想你就不能实现它。你只需要遵守我们的第二定律:<script>Svelte 组件标签内的代码必须是有效的 JS。同样,这不是技术限制,而是哲学限制。Svelte 的创建者和核心开发人员多次重申这一点。在语法层面上,我们甚至不再谈论超集,而是平等。任何 Svelte JS 都是有效的 JS(请注意,与“任何 JS 都是有效的 JSX”相比,关系的成员已被交换)。

另一方面,Svelte JS 也不是 JS 的语义超集。一些 JS 程序在解释为纯 JS 时的行为与使用 Svelte 解释时的行为不同,因为 Svelte 重载了一些具有不同含义的结构(如$:or )。export let prop

这个约束在这里影响了我们,因为class有效的变量名不是 JS,并且 Svelte 组件的属性被定义为 JS 变量。但是你可以绕过它:

<script>
  // can't do, not valid JS:
  //    export let class

  // but:
  let cls = ''
  export { cls as class } // valid JS
</script>

<div class={class} />

然后将像这样使用该组件(现场示例):

<script>
  import MyComponent from './MyComponent.svelte'
</script>

<MyComponent class="blue" />

所以你也可以class在 Svelte 中为组件使用关键字。

呸。希望你喜欢一个成熟的答案!

总而言之,如果一些主要框架允许使用class关键字而一些不允许使用,那是出于哲学原因。作为 JS 的超集,JSX 尊重这个约束是完全有意义的。Svelte 的 HTMLX 无缘无故地实现这个约束是没有意义的(并且在这个过程中不再是 HTML 的超集)。此外,React 更注重数学纯度,而 Svelte 更注重代码表达性和便利性。与优秀的软件一样,一切都在权衡之中!


推荐阅读