1 Selectors API
Selectors API(参见 W3C 网站上的 Selectors API Level 1)是 W3C 推荐标准,规定了浏览器原生支
持的 CSS 查询 API。支持这一特性的所有 JavaScript 库都会实现一个基本的 CSS 解析器,然后使用已有的 DOM 方法搜索文档并匹配目标节点。
1.1 querySelector()
// 取得 ID 为"myDiv"的元素
let myDiv = document.querySelector("#myDiv");
1.2 querySelectorAll()
querySelectorAll()返回的 NodeList 实例一个属性和方法都不缺,但它是一个静态的“快照”,而非“实时”的查询。这样的底层实现避免了使用 NodeList 对象可能造成的性能问题。
1.3 matches()
使用这个方法可以方便地检测某个元素会不会被 querySelector()或 querySelectorAll()方法返回。
if (document.body.matches("body.page1")){
// true
}
2 元素遍历
childElementCount,返回子元素数量(不包含文本节点和注释);
firstElementChild,指向第一个 Element 类型的子元素(Element 版 firstChild);
lastElementChild,指向最后一个 Element 类型的子元素(Element 版 lastChild);
previousElementSibling ,指向前一个 Element 类型的同胞元素( Element 版
previousSibling);
nextElementSibling,指向后一个 Element 类型的同胞元素(Element 版 nextSibling)。
在支持的浏览器中,所有 DOM 元素都会有这些属性,为遍历 DOM 元素提供便利。这样开发者就
不用担心空白文本节点的问题了。
3 HTML5
3.1 CSS 类扩展
1. getElementsByClassName()
这个方法只会返回以调用它的对象为根元素的子树中所有匹配的元素。在 document 上调用getElementsByClassName()返回文档中所有匹配的元素,而在特定元素上调用 getElementsByClassName()则返回该元素后代中匹配的元素。因为返回值是 NodeList,所以使用这个方法会遇到跟使用 getElementsByTagName()和其他返回 NodeList 对象的 DOM 方法同样的问题。
2. classList 属性
// 删除"disabled"类
div.classList.remove("disabled");
// 添加"current"类
div.classList.add("current");
3.2 焦点管理
无障碍 Web 应用程序的一个重要方面就是焦点管理,HTML5 增加了辅助 DOM 焦点管理的功能。是 document.activeElement,始终包含当前拥有焦点的 DOM 元素。页面加载时,可以通过用户输入(按 Tab 键或代码中使用 focus()方法)让某个元素自动获得焦点。
let button = document.getElementById("myButton");
button.focus();
console.log(document.activeElement === button); // true
document.hasFocus()方法,该方法返回布尔值,表示文档是否拥有焦点:
console.log(document.hasFocus());
3.3 HTMLDocument 扩展
1. readyState 属性
document.readyState 属性有两个可能的值:
loading,表示文档正在加载;
complete,表示文档加载完成。
2. compatMode 属性
IE 为 document 添加了 compatMode 属性,这个属性唯一的任务是指示浏览器当前处于什么渲染模式。标准模式下 document.compatMode 的值是"CSS1Compat",而在混杂模式下,document.compatMode 的值是"BackCompat"。
3. head 属性
let head = document.head;
3.4 字符集属性
console.log(document.characterSet); // "UTF-16"
document.characterSet = "UTF-8";
3.5 自定义数据属性
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
// 取得自定义数据属性的值
let appId = div.dataset.appId;
let myName = div.dataset.myname;
自定义数据属性非常适合需要给元素附加某些数据的场景,比如链接追踪和在聚合应用程序中标识页面的不同部分。另外,单页应用程序框架也非常多地使用了自定义数据属性。
3.6 插入标记
1. innerHTML 属性
不同浏览器的innerHTML 返回不完全一样的值。
2. 旧 IE 中的 innerHTML
3. outerHTML 属性
读取 outerHTML 属性时,会返回调用它的元素(及所有后代元素)的 HTML 字符串。在写入outerHTML 属性时,调用它的元素会被传入的 HTML 字符串经解释之后生成的 DOM 子树取代。
4. insertAdjacentHTML()与 insertAdjacentText()
它们都接收两个参数:要插入标记的位置和要插入的 HTML 或文本。第一个参数必须是下列值中的一个:
“beforebegin”,插入当前元素前面,作为前一个同胞节点;
“afterbegin”,插入当前元素内部,作为新的子节点或放在第一个子节点前面;
“beforeend”,插入当前元素内部,作为新的子节点或放在最后一个子节点后面;
“afterend”,插入当前元素后面,作为下一个同胞节点
// 作为前一个同胞节点插入
element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>");
element.insertAdjacentText("beforebegin", "Hello world!");
5. 内存与性能问题
使用本节介绍的方法替换子节点可能在浏览器(特别是 IE)中导致内存问题。比如,如果被移除的子树元素中之前有关联的事件处理程序或其他 JavaScript 对象(作为元素的属性),那它们之间的绑定关系会滞留在内存中。在使用 innerHTML、outerHTML 和insertAdjacentHTML()之前,最好手动删除要被替换的元素上关联的事件处理程序和JavaScript 对象。
6. 跨站点脚本
如果页面中要使用用户提供的信息,则不建议使用 innerHTML。与使用 innerHTML 获得的方便相比,防止 XSS 攻击更让人头疼。此时一定要隔离要插入的数据,在插入页面前必须毫不犹豫地使用相关的库对它们进行转义。
3.7 scrollIntoView()
scrollIntoView()方法存在于所有 HTML 元素上,可以滚动浏览器窗口或容器元素以便包含元素进入视口。这个方法的参数如下:
- alignToTop 是一个布尔值。
true:窗口滚动后元素的顶部与视口顶部对齐。
false:窗口滚动后元素的底部与视口底部对齐。 - scrollIntoViewOptions是一个选项对象。
behavior:定义过渡动画,可取的值为"smooth"和"auto",默认为"auto"。
block:定义垂直方向的对齐,可取的值为"start"、“center”、“end"和"nearest”,默认为"start"。 inline:定义水平方向的对齐,可取的值为"start"、“center”、“end"和"nearest”,默认为"nearest"。 - 不传参数等同于 alignToTop 为 true。
// 尝试将元素平滑地滚入视口
document.forms[0].scrollIntoView({behavior: 'smooth', block: 'start'});
4 专有扩展
4.1 children 属性
IE9 之前的版本与其他浏览器在处理空白文本节点上的差异导致了 children 属性的出现。
4.2 contains()方法
DOM 编程中经常需要确定一个元素是不是另一个元素的后代。IE 首先引入了 contains()方法,让开发者可以在不遍历 DOM 的情况下获取这个信息。contains()方法应该在要搜索的祖先元素上调用,参数是待确定的目标节点。
如果目标节点是被搜索节点的后代,contains()返回 true,否则返回 false。下面看一个例子:
console.log(document.documentElement.contains(document.body)); // true
4.3 插入标记
1. innerText 属性
innerText 属性对应元素中包含的所有文本内容,无论文本在子树中哪个层级。在用于读取值时,innerText 会按照深度优先的顺序将子树中所有文本节点的值拼接起来。在用于写入值时,innerText会移除元素的所有后代并插入一个包含该值的文本节点。
2. outerText 属性
outerText 是一个非标准的属性,而且也没有被标准化的前景。因此,不推荐依赖这个属性实现重要的操作。
5 小结
虽然 DOM 规定了与 XML 和 HTML 文档交互的核心 API,但其他几个规范也定义了对 DOM 的扩展。很多扩展都基于之前的已成为事实标准的专有特性标准化而来。本章主要介绍了以下 3 个规范。
Selectors API 为基于 CSS 选择符获取 DOM 元素定义了几个方法:querySelector()、querySelectorAll()和 matches()。
Element Traversal 在 DOM 元素上定义了额外的属性,以方便对 DOM 元素进行遍历。这个需求是因浏览器处理元素间空格的差异而产生的。
HTML5 为标准 DOM 提供了大量扩展。其中包括对 innerHTML 属性等事实标准进行了标准化,还有焦点管理、字符集、滚动等特性。