React 16中的class与className有何区别?

114

我看到React 16允许将属性传递到DOM中。所以,这意味着可以使用“class”而不是className,对吗?

我只是想知道除了向后兼容以外,仍然使用className是否有优势。


className是唯一支持的属性,但在v16中,“具有不同规范React名称的已知属性”发生了变化。在v15中,React会发出警告并忽略它们,在v16中,它会发出警告,但将值转换为字符串并通过。文档清楚地回答了您的问题:“始终使用所有支持的属性的规范React命名”。请参见https://reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html#changes-in-detail - lifeisfoo
12个回答

128

class 是 Javascript 中的一个关键字,而 JSX 则是 JavaScript 的扩展。这就是为什么 React 使用 className 而不是 class 的主要原因。

在这方面没有任何改变。

再详细解释一下,关键字 意味着在语言语法中,该标记具有特殊含义。例如,在以下代码中:

class MyClass extends React.Class {

Token class表示下一个标记是标识符,接下来是一个类声明。请参见JavaScript关键字+保留字

标记为关键字意味着我们不能在某些表达式中使用它,例如:

// invalid in older versions on Javascript, valid in modern javascript
const props = {
  class: 'css class'
}

// valid in all versions of Javascript
const props = {
 'class': 'css class'
};

// invalid!
var class = 'css';

// valid
var clazz = 'css';

// valid
props.class = 'css';

// valid
props['class'] = 'css';

问题之一是没有人能知道未来是否会出现其他问题。每种编程语言仍在不断发展,class 可能会在某些新的冲突语法中实际使用。

className 没有这样的问题存在。


13
props.class = 'css' 这是完全有效的。 - daGo
1
无论是"class"还是"className"都可以使用。例如,当我使用<div class="input-group">时,它会正确地呈现我的Bootstrap输入组。使用className也可以。使用其他任何内容或删除它都不起作用。 - Welcor

41

更新(2020年8月):

在同一讨论串上,Dan Abramov发表了评论

这是提案中最具争议的部分。自那时以来,我们发布了Hooks,鼓励编写函数组件。在函数组件中,我们通常建议使用解构来处理props,但是你不能编写{ class, ... },因为它会导致语法错误。因此,总体而言,这并不清晰且不够人性化。我认为未来我们可能会重新审视这个问题,或者至少让class不再警告并让人们随意使用。但目前,我们将搁置这个想法。

所以,不行。


(2018年8月)

React团队在不久的将来实际上将转换为使用class而不是classNamesource):

  • classNameclass#4331,另见下面的#13525 (comment))。这已经被提出无数次了。我们已经允许在React 16中向DOM节点传递类。它所造成的混淆不值得它试图保护的语法限制。

为什么要切换而不支持两者?

如果我们在没有警告的情况下同时支持两种,那么社区就会分裂,因为他们会选择使用哪一个。每个npm上接受类属性的组件都必须记得转发两者。如果中间有一个组件不遵循规则并且只实现了一个属性,则类会丢失 - 或者你会冒着底部的classclassName“不一致”的风险,而React无法解决这个冲突。因此,我们认为这比现状更糟糕,希望避免这种情况。

所以你应该保持关注。
只要API期望使用className,我仍然建议使用它。


8
似乎不再是这种情况了。请参见:https://github.com/facebook/react/pull/10169的末尾。 - machineghost
4
@machineghost的#13525(进行转变)是在2018年8月31日开启的。另一方面,#10169已于2017年8月4日关闭。因此,我认为它仍然相关。 - Maor Refaeli
4
不相关。他们意识到“class”是一个关键字,不能在许多表达式中使用。 - Sulthan

19

为了更好地解释,除了已经给出的其他好的答案:

你会注意到React使用className而不是传统的DOM类。从文档中可以看出,“由于JSX是JavaScript,因此不建议使用诸如class和for之类的标识符作为XML属性名称。相反,React DOM组件期望DOM属性名称,例如className和htmlFor。”

http://buildwithreact.com/tutorial/jsx

另外,为了引用zpao(一位React贡献者/ Facebook员工)

我们的DOM组件(大多数情况下)使用JS API,因此我们选择使用JS属性(node.className,而不是node.class)。


10

9

React文档建议使用规范的React属性名称,而不是传统的Javascript命名方式,因此即使React允许将属性传递到DOM中,它也会发出警告。

来自文档:

Known attributes with a different canonical React name:

    <div tabindex="-1" />
    <div class="hi" />

React 15: Warns and ignores them.
React 16: Warns but converts values to strings and passes them through.
Note: always use the canonical React naming for all supported attributes.

4
为什么会有这个建议呢? - Aslan French

5

ReactJS中的Class与className Class是ReactJS中的保留字,就像function是JavaScript中的保留字一样。这就是为什么我们使用"className"这个词来表示类的原因。


4
React团队没有提供关于这个问题的真正解释,但人们会推测它与Javascript中从ES2015+开始引入的保留关键字"class"有所区别。
即使您在创建元素时在元素配置中使用"class",也不会抛出任何编译/渲染错误。

3
在ReactJS中,我们处理的是JSX而不是HTML,正如大家所知。JSX希望您使用className,因为它是基础javascript DOM API! class在JS中是保留关键字,并不是我们不使用class而改用className的主要原因。这是因为我们引用了那个DOM API。

3

首先,让我们想一想为什么在第一次使用时使用 className 而不是 class

最近我观看了 Joel Denning 的CSS in React conference video,他认为 className 之所以被使用是因为 class 是 JavaScript 中的关键字。虽然我倾向于同意他的看法,但我仍然不是完全清楚。以下是他视频中的解释和我的一些输入:

打开 Babel 并编译以下 JSX 片段:

const element = <div className="foo" />;
const element2 = <div class="foo" />;

Babel将其编译为:
var element = /*#__PURE__*/React.createElement("div", {
  className: "foo"
});
var element2 = /*#__PURE__*/React.createElement("div", {
  "class": "foo"
});

看看class是如何被视为字符串"class"的,所以没有JavaScript关键字的问题。
HTML元素有像class这样的属性,然后一旦解析,就会创建一个带有className属性的DOM节点。属性和属性之间的区别?请参见HTML中属性和特性的区别是什么?
HTML属性值只能是字符串,而DOM属性可以具有任何值。当涉及到处理类名时,我不确定这对于什么有用,但更新DOM属性比属性更清洁:
const div = document.createElement('div');

// Attribute update
div.setAttribute('class', 'foo');

// Property update
div.className = 'foo';

此外,更新DOM属性会触发重新渲染,这与类名是可变状态的想法相吻合。
属性往往用于初始化DOM属性,但是class属性和className属性是反射的,即更新className属性会导致class属性以相同的值进行更新...这使得选择className的原因令人困惑,也许是因为语义上将属性与可以更新的值相关联?我不知道...
这太令人困惑了,React允许在className旁边使用class(如问题中所述)。来自https://github.com/facebook/react/issues/13525

className → class (#4331,另请参见下面的#13525(comment)). 这个问题已经被提出无数次了。在React 16中,我们已经允许将class传递到DOM节点中。这种混淆并不值得它试图保护的语法限制。我们不会仅仅因为这个改变而做出这个改变,但与以上所有内容相结合,这是有意义的。请注意,我们不能只是允许两者都存在而没有警告,因为这会使组件生态系统很难处理。每个组件都需要学习如何正确处理两者,并且存在冲突的风险。由于许多组件处理className(例如通过追加到它),这太容易出错了。

我认为对于这个问题没有具体的答案。我喜欢使用属性而不是属性来更新某些东西背后的语义,但如果你带我回到当初决定使用className而不是class的时候,我会说这是不必要的。

tldr;回答你的问题,我会坚持使用className,避免class的警告,并且这是大多数其他React开发人员熟悉的方法,因此您的代码将更易于阅读。

还不满意?阅读https://github.com/facebook/react/issues/13525#issuecomment-417818906


0
问题在于,你看到的React代码并不是HTML - 实际上它是JSX,是JavaScript的扩展(基本上是JavaScript + 更多一点)。
问:我们可以使用class来表示HTML属性:“class”吗?

This is JSX

由于它是JavaScript,你不能使用单词class,因为那是一个特殊的JavaScript字,被"保留"了(JavaScript规定了一些可以和不可以使用的单词)。

既然class是一个保留字,那么在我们的"html" code JSX中如何编写类呢?因为那个单词是"保留"的,不能像那样使用。解决方法是使用:"className"代替"class",这样JSX就知道你正在处理HTML类属性,而不是JavaScript的class关键字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接