Firefox 3.6 中的 ClassList

本文由法国 OpenWeb 爱好者 Anthony Ricaud 撰写。

为什么需要 classList

动态 Web 应用程序通常需要其内部机制的视觉反馈,或者需要根据用户的操作显示不同的视觉元素。

为了轻松更改用户界面,您可以通过 DOM API(document.createElementdiv.removeChildelt.style.color 等)添加/删除/编辑元素,但只需更新元素的 class 属性即可更改它们如何通过 CSS 显示和设置样式,这更容易。

让我们举个例子。假设您想显示一个具有两种模式的表单:基本模式和具有额外选项的专家模式。

这可以通过 CSS 规则来完成:每种模式都有自己的类和 CSS 代码集。

#anexpertinput.basic {
  display: none;
}
#anexpertinput.expert {
  display: inline;
}

要动态更改元素的类,可以使用 element.className。但是,您可能希望添加、删除或切换单个类。过去有两种方法可以做到这一点,使用库或使用正则表达式编写复杂的代码。现在,使用名为 classList 的新 HTML5 API 还有另一种方法,该 API 在 Firefox 3.6 中实现。

让我们看看它如何简化您的代码并同时提高性能。

classList API

这是一个示例,向您展示 classList API 的外观

// By default, start without a class in the div: 
// Set "foo" as the class by adding it to the classList div.classList.add('foo'); // now
// Check that the classList contains the class "foo" div.classList.contains('foo'); // returns true // Remove the class "foo" from the list div.classList.remove('foo'); // now
// Check if classList contains the class "foo" div.classList.contains('foo'); // returns false: "foo" is gone // Check if class contains the class "foo", // If it does, "foo" is removed, if it doesn't, it's added div.classList.toggle('foo'); // class set to
div.classList.toggle('foo'); // class set to

演示

让我们回到我们最初关于具有基本模式和专家模式的表单的示例 - 查看 实时演示 以查看其运行情况。

如您在下面的代码中看到的,您可以使用一行 JavaScript 在这两种模式之间切换。


Blablablablabla...

#box.expert > #help,
#box.expert > label[for="postpone"],
#box.expert > label[for="lang"] {
   display: none;
}

有关 classList 的更多详细信息,请参阅 Mozilla 文档HTML5 规范

性能

使用 classList API 不仅更容易,而且功能更强大。查看使用 Firefox 3.6 我们观察到的情况

benchmark classList

互操作性

由于其他浏览器供应商尚未实现 HTML5 classList API,因此您仍然需要回退代码。您可以使用 此示例代码 作为回退。

要了解知名 JavaScript 库中 classList 的当前实现情况,请参阅

关于 Paul Rouget

Paul 是一位 Firefox 开发人员。

更多 Paul Rouget 的文章……


16 条评论

  1. thinsoldier

    关于:http://demos.hacks.mozilla.org/openweb/classList/

    Safari 中的“普通测试”比 Firefox 中的“原生”测试快 :(

    2010 年 1 月 29 日 13:00

  2. shawnee

    太棒了!我们很长时间以来一直需要对这种 Web 浏览器行为进行合理的解释……。我喜欢大多数 JavaScript 只是被美化的、带注释的 CSS 行为。

    2010 年 1 月 29 日 13:11

  3. Boris

    链接的基准测试似乎毫无用处;特别是它主要衡量引擎解析非常长的类属性值需要多长时间。由于设置或取消设置 1000 个不同类的用例并不常见,为什么我们要测试它呢?

    2010 年 1 月 29 日 13:12

  4. Edwin Martin

    测试极端情况非常有用。如果您的功能在极端情况下有效且足够快,您可以非常确定它将在正常情况下执行。

    2010 年 1 月 29 日 13:27

  5. shawnee

    我评论的进一步证明:http://arstechnica.com/apple/news/2008/04/javascript-slows-down-the-internet-webkit-to-the-rescue.ars

    2010 年 1 月 29 日 14:15

  6. Boris

    如果极端情况与正常使用具有相同的瓶颈,那么 Edwin 的说法是正确的。如果不是,那么它实际上并不能告诉你太多。

    或者换句话说,我可以在不花费太多精力的情况下,可能将这个“极端情况”的速度提高 2-3 倍,而不会加快正常情况的速度;实际上,它可能会减慢正常情况的速度。

    2010 年 1 月 29 日 19:28

  7. Azat Razetdinov

    切换方法中强烈需要第二个参数
    classList.toggle(‘selected’, someObject.isSelected())。

    2010 年 1 月 31 日 03:35

  8. Anthony Ricaud

    本文的重点不是基准测试,而是新的、更简单的 API。

    2010 年 2 月 1 日 10:42

  9. Paul Rouget

    关于基准测试,我同意它并不代表通常的情况。但是您不能只使用正常用例来解释和展示此类改进(性能在这里,但并不明显)。

    夸大测试用例是演示增强功能的好方法。

    但正如 Anthony 所说,本文的重点是 API,它使用起来要容易得多。

    2010 年 2 月 1 日 11:15

  10. Boris

    Anthony、Paul,您可以轻松地编写一个更能代表实际用法的基准测试,只需向多个元素添加,或对同一元素上的添加+删除进行计时,或者人们将_真正_使用这种方法。如果您无法找到人们使用它的方式,以便改进可见,那么性能差异就无关紧要。

    2010 年 2 月 1 日 11:41

  11. WalterK

    在演示中,当其他元素“隐藏”时,复制和粘贴包含“隐藏”区域的文本选择仍然包含“隐藏”元素。这是不幸的副作用,还是有办法真正隐藏复制/粘贴中的元素?我在过度依赖 JS/CSS 毫无理由的商业网站上也看到了类似的烦人副作用。

    2010 年 2 月 3 日 13:31

  12. nemo

    嗨,WalterK。这显然是因为“隐藏”使用了 display: none;。

    如果您希望它与复制/粘贴一起使用,解决方案是从 DOM 中添加/删除该块。这可以相当容易/快速地完成,尤其是在该块很好地包含的情况下。

    当然,如果您要这样做,最好使默认值可见,并且仅在 JavaScript 操作(如 onclick)上隐藏。这样,表单对于非 JavaScript 情况下的降级效果会很好。

    但是,我自己一直都在使用 display: none;。我并没有真正认为这个复制/粘贴问题对于我正在显示/隐藏的内容至关重要。

    例如,在这种情况下,我确实不明白它为什么对你来说很重要。
    鉴于如今网络上隐藏的大量内容,脚本和其他垃圾,复制网页的大部分内容一定会获取各种内容。

    2010 年 2 月 4 日 12:35

  13. ……很高兴听到 Thomas Bassetto 说 addClass 确实已被 HTML5 的 ClassList API 替代,后者看起来很棒。element.classList 今天在 Firefox 3.6 中可用,并且根据……

    2010 年 5 月 26 日 06:56

  14. austin

    使用小规模测试很难注意到您在哪里被减速,您有一个或两个,并且因素很小,您的仪器根本无法记录它,因此您夸大了它,将其推向极端并查看您是否仍然看到良好的性能。这是一个整体性能测试,也是可扩展性测试(有人可能会最终拥有非常大的类列表,我可以在漫长的开发周期中看到自己拥有大型类列表,此外,如果它内置于某种库或 API 中,人们会向其中添加一些内容,直到您拥有 10 或 100 个类列表。虽然可能不太常见,但我预计它将成为新的类列表 API 的真实结果。)
    但重点是要表明原生 API 和非原生 API 之间存在性能差异(这有时会使需要每秒调用该函数数百次的庞大库产生差异)

    2010 年 6 月 22 日 11:55

  15. ……原文作者:Anthony Ricaud – 前往原文……

    2010 年 7 月 20 日 06:17

  16. cc young

    笔记

    如果 classList.add(‘c1’) 且 c1 已经存在于 classList 中,则为良性;也就是说,如果 classList.remove(‘c1’) 则 classList.contains(‘c1’) 为 false

    如果 classList.add(‘c1 c2’) => 错误;而 className(‘c1 c2’) 添加两个类

    2011 年 7 月 18 日 06:46

本文评论已关闭。