Vue 是什么让开发人员能够在 DOM 元素上使用 class 属性?

What is it about Vue that enables developers to use the class property on DOM elements?

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

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

编辑: Svelte does not use virtual DOM 并且您可以 将 class prop 与 Svelte 一起使用。

你不能将 class 与 React 一起使用,因为 React 使用 React DOM,它使用驼峰式 属性 名称,而不是经典的 HTML 属性。 这就是为什么在 JSX(React 渲染语言)中,你必须使用 className,而不是 class

Vue 使用经典的 HTML 模板,因此 class 是允许的。

使用 Svelte,您应该可以在模板中使用 class 关键字。

React 库使用 JSX 渲染任何 DOM 元素。 JSX 是 JS 的一种扩展,从 javascript 渲染 HTML。 JSX 在渲染到浏览器之前被转译。因此必须使用 className 而不是 class。但是,从一个 reactjs 版本到另一个版本有一些进步。

好像已经有人问过类似的问题了。找到更多解释

根据我的研究答案:感谢他们内置的功能。

我在 Vue.js https://github.com/vuejs/vue/blob/dev/dist/vue.js 的一侧发现 Vue 正在将 class 从 JavaScript 对象绑定到 Node。 (vue) 节点元素与 JavaScript 一起使用以分配给 DOM elm 所有 classes.

JavaScript 代码 el.setAttribute('class', cls) 正在确认。

  function transformNode (el, options)

从这里您将在第 5503 行找到函数:

  function genClassForVnode (vnode)

其中使用了

  function renderClass (staticClass, dynamicClass)

此函数随后被

使用
function updateClass (oldVnode, vnode) {
    var el = vnode.elm;
    var data = vnode.data;
    var oldData = oldVnode.data;
  [...]  
    var cls = genClassForVnode(vnode);

    // handle transition classes
    var transitionClass = el._transitionClasses;
    if (isDef(transitionClass)) {
      cls = concat(cls, stringifyClass(transitionClass));
    }

    // set the class
    if (cls !== el._prevClass) {
      el.setAttribute('class', cls);
      el._prevClass = cls;
    }
  }

注意:以下函数比较有意思: function addClass(el, cls) 第 7873 行 function bindObjectListeners(data, value) 第 2866 行

有帮助吗?

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

中一样

在这里为 Svelte 代言。

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

JavaScript frameworks like React and Svelte don't allow developers to use the class property on a virtual DOM element because the class keyword is reserved in JavaScript.

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

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

为了做到这一点,JSX 必须尊重 JS 的每一个约束,其中 "class is a reserved keyword"。这就是 React 不允许使用 class 关键字的原因。

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

这是一个哲学约束。有一次,JSX 开发人员必须权衡不能使用 class 关键字的不便,而不是突然成为 JS 的严格超集。一方面,您获得了一点好处,另一方面,您突然从纯数学超集降级为 "yet another random template language".

很容易感受到来自 React 的强烈数学倾向,它强调纯函数、"view as a function of the state"、单向数据流等。这实际上是 React 的一个非常重要的收获。他们将数学的许多好处引入到日常应用程序开发中。因此,(对我而言)完全可以理解,这群开发人员偏爱(赞成)纯粹性而不是次要的便利。

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

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

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

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

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

如果不是,它就不是 HTML 的适当超集。

在这种情况下,class 实际上是 "directive",这意味着它比纯粹的 HTML class 更强大。例如:

<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 关键字,这是毫无疑问的。对于原生元素,即。

现在,组件的情况有点不同。我前面提到的2条法则来了。

第一个是 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 集应用到包含的组件上的哪些元素。因此,在这种情况下,它什么都不做。它会将控件交还给您。

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

另一方面,Svelte JS 也不是 JS 的语义超集。某些 JS 程序在被解释为纯 JS 时的行为与在用 Svelte 解释时的行为不同,因为 Svelte 重载了一些具有不同含义的结构(如 $: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} />

这个组件可以这样使用 (live example):

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

<MyComponent class="blue" />

因此您也可以在 Svelte 中为组件使用 class 关键字。

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

总而言之,如果一些主要框架允许使用 class 关键字而另一些则不允许,这是出于哲学原因。作为 JS 的超集,JSX 完全有理由遵守这一约束。对于 Svelte 的 HTMLX 来说,无缘无故地实施这个约束是没有意义的(并且在这个过程中不再是 HTML 的超集)。此外,React 更注重数学的纯粹性,而 Svelte 更注重代码的表现力和便利性。一如既往的好软件,一切都在权衡之中!