自 HTML4 被广泛采用以来,Web 开发中一个主要的变化是 class 属性用得越来越多,其用处是为 元素添加样式以及语义信息。自然地,JavaScript 与 CSS 类的交互就增多了,包括动态修改类名,以及 根据给定的一个或一组类名查询元素,等等。为了适应开发者和他们对 class 属性的认可,HTML5 增 加了一些特性以方便使用 CSS 类。
1. getElementsByClassName()
getElementsByClassName()是 HTML5 新增的最受欢迎的一个方法,暴露在 document 对象和 所有 HTML 元素上。 这个方法脱胎于基于原有 DOM 特性实现该功能的 JavaScript 库,提供了性能高好 的原生实现。 getElementsByClassName()方法接收一个参数,即包含一个或多个类名的字符串,返回类名中 包含相应类的元素的 NodeList。如果提供了多个类名,则顺序无关紧要。下面是几个示例:
// 取得所有类名中包含"username"和"current"元素
// 这两个类名的顺序无关紧要
let allCurrentUsernames = document.getElementsByClassName("username current");
// 取得 ID 为"myDiv"的元素子树中所有包含"selected"类的元素
let selected = document.getElementById("myDiv").getElementsByClassName("selected");
这个方法只会返回以调用它的对象为根元素的子树中所有匹配的元素。在 document 上调用 getElementsByClassName()返回文档中所有匹配的元素,而在特定元素上调用 getElementsBy- ClassName()则返回该元素后代中匹配的元素。 如果要给包含特定类(而不是特定 ID 或标签)的元素添加事件处理程序,使用这个方法会很方便。 不过要记住,因为返回值是 NodeList,所以使用这个方法会遇到跟使用 getElementsByTagName() 注意 因为 HTML5 覆盖的范围极其广泛,所以本节主要讨论其影响所有 DOM 节点的部 分。
和其他返回 NodeList 对象的 DOM 方法同样的问题。 IE9 及以上版本,以及所有现代浏览器都支持 getElementsByClassName()方法。
2. classList 属性
<div class="bd user disabled">...</div> 17
这个
元素有 3 个类名。要想删除其中一个,就得先把 className 拆开,删除不想要的那个, 再把包含剩余类的字符串设置回去。比如: 要操作类名,可以通过 className 属性实现添加、删除和替换。但 className 是一个字符串, 所以每次操作之后都需要重新设置这个值才能生效,即使只改动了部分字符串也一样。以下面的 HTML 代码为例:
let classNames = div.className.split(/\s+/); 19
// 要删除"user"类
let targetClass = "user";
// 把类名拆成数组
// 找到要删除类名的索引
let idx = classNames.indexOf(targetClass);
// 如果有则删除 if (idx > -1) {
classNames.splice(i,1);
}
// 重新设置类名
div.className = classNames.join(" ");
这就是从
元素的类名中删除"user"类要写的代码。替换类名和检测类名也要涉及同样的算 法。添加类名只涉及字符串拼接,但必须先检查一下以确保不会重复添加相同的类名。很多 JavaScript 库为这些操作实现了便利方法。 HTML5 通过给所有元素增加 classList 属性为这些操作提供了更简单也更安全的实现方式。 classList 是一个新的集合类型 DOMTokenList 的实例。与其他 DOM 集合类型一样,DOMTokenList 也有 length 属性表示自己包含多少项,也可以通过 item()或中括号取得个别的元素。此外, DOMTokenList 还增加了以下方法。 24 add(value),向类名列表中添加指定的字符串值 value。如果这个值已经存在,则什么也不做。 contains(value),返回布尔值,表示给定的 value 是否存在。 remove(value),从类名列表中删除指定的字符串值 value。 toggle(value),如果类名列表中已经存在指定的 value,则删除;如果不存在,则添加。 这样以来,前面的例子中那么多行代码就可以简化成下面的一行: div.classList.remove("user"); 这行代码可以在不影响其他类名的情况下完成删除。其他方法同样极大地简化了操作类名的复杂 性,如下面的例子所示:
// 删除"disabled"类 div.classList.remove("disabled");
// 添加"current"类 div.classList.add("current");
div.classList.toggle("user");
// 检测类名
if (div.classList.contains("bd") && !div.classList.contains("disabled")){
// 执行操作 )
// 迭代类名
for (let class of div.classList){
doStuff(class);
}
添加了 classList 属性之后,除非是完全删除或完全重写元素的 class 属性,否则 className 属性就用不到了。IE10 及以上版本(部分)和其他主流浏览器(完全)实现了 classList 属性。