使用.classLIst将类添加到已经具有该类的元素中,是否有任何危害

时间:2018-07-06 16:39:11

标签: javascript css

这个问题的答案(addClass to an element with that class already?)表明,使用jQuery时,如果您.addClass('foo')在已经具有foo类的元素上不会出现问题。

我很好奇element.classList的{​​{1}}方法也是如此。

特别是我有一个名为.add的函数,每当范围滑块更新时都会调用该函数。每秒可能会发生多次。根据传递给update()的值,我向元素添加和删除某些类。

如果该值连续落在某个范围内,我最终会一遍又一遍地添加相同的类。

我的问题是,我可以让update()在一秒钟内运行50次,而不会给用户体验,内存,处理器使用等带来任何负面影响。这是否可以接受?

谢谢。

2 个答案:

答案 0 :(得分:2)

不要这样做:

if (!el.classList.contains("foo")) {
    el.classList.add("foo");
}

这样做:

el.classList.add("foo");

原因:

  • .classList 属性是一个 DOMTokenList 对象。
  • 它代表一组以空格分隔的标记
  • 标记(即类名)区分大小写。
  • 编程中的术语“集合”是指一个容器,其中包含一个唯一的项目集合,其顺序未指定。
  • 换句话说,一个集合不能包含重复项。
  • 定义 DOMTokenList 的 DOM 规范将其定义为一个容器,其中包含区分大小写、修剪空格、唯一的项目。
  • 所有读取修改DOMTokenList(例如DOMTokenList.add())的方法都会自动修剪任何周围的空白并从集合中删除重复项。
  • 这意味着如果您尝试 add() 同一个 className 两次,它不会添加重复项。

这是一个例子:

<span class="    d   d e f"></span>

// Output: DOMTokenList(3) ["d", "e", "f", value: "    d   d e f"]
// As you can see, it only contains the unique values.
console.log(document.querySelector("span").classList);

// Try to add a duplicate value.
document.querySelector("span").classList.add("e");

// Output: DOMTokenList(3) ["d", "e", "f", value: "d e f"]  
// As you can see again, it only contains the unique values.
console.log(document.querySelector("span").classList);

// In fact, the act of duplicates being detected while trying
// to add more classes, results in the "class" attribute itself
// being cleaned up and trimmed:
// Output: "d e f"
console.log(document.querySelector("span").getAttribute("class"));

好吧,那么为什么不应该使用 .contains() 来“避免在不必要时调用 .add()”?因为:

  • .contains() 函数和 .add() 函数使用完全相同的本机代码来搜索唯一集以查看它是否包含类。
  • 因此,它们检测 className 是否存在的技术之间没有速度差异。
  • 换句话说,调用 .add() 将搜索整个集合,如果它已经包含 className,该函数将简单地中止。是的,它有时还会在必要时清理“class”HTML 属性,但仅限于必要时。
  • 另一方面,如果您在 .contains() 之前调用 .add() 并且最终添加了 className,那么您只需通过两个不同的函数对 className 进行两次搜索。
  • 但更重要的是:在每次尝试添加类时都使用巨大的 if (!el.classList.contains("foo")) { ... } 样板,会使代码变得笨拙且不可读。
  • DOM 规范旨在满足程序员需要的用例,既现代又高效。这意味着,您应该使用 .add() 添加一个类(即使它已经存在),并使用 .remove() 删除一个类(即使它已经丢失)。

不要浪费键盘的生命和程序员的眼睛在笨重的样板上。仅当您真正关心找出元素是否具有某个类时才使用 .contains()。 ?

另请记住,DOMTokenList 还有许多其他有用的功能:

  • https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
  • .replace(oldToken, newToken):用新令牌替换现有令牌。如果旧令牌不存在,.replace() 会立即返回 false,而不会将新令牌添加到令牌列表中。
  • .toggle(token [, force]):从列表中删除给定的标记并返回 false,或者如果标记不存在,则添加它并且函数返回 true。或者,如果您包含 force 参数:如果包含,则将切换切换为单向操作。如果设置为 false,则令牌只会被移除,而不会被添加。如果设置为 true,则只会添加令牌,而不会删除。
  • 这两个额外的函数可以让你实现大部分你想做的事情,而不是“如果不是 .contains() 然后 .add()”或类似的代码。如果您个人需要知道令牌是否存在,您应该只使用“.contains()”。

答案 1 :(得分:0)

虽然不会造成任何伤害,但最好像这样包装它:

if(!elem.classList.contains('foo')) elem.classList.add('foo');