第 11 章 DOM扩展

68 阅读6分钟

DOM 的两个主要的扩展是 Selectors API(选择符 API)和 HTML5。

11.1 选择符 API

Selectors API Level 1 的核心是两个方法:querySelector()和 querySelectorAll()。

11.1.1 querySelector()方法

querySelector()方法接收一个 CSS 选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回 null。

//取得 body 元素
var body = document.querySelector("body");
//取得 ID 为"myDiv"的元素
var myDiv = document.querySelector("#myDiv");
//取得类为"selected"的第一个元素
var selected = document.querySelector(".selected");
//取得类为"button"的第一个图像元素
var img = document.body.querySelector("img.button");

11.1.2 querySelectorAll()方法

querySelectorAll()方法接收的参数与 querySelector()方法一样,都是一个 CSS 选择符,但返回的是所有匹配的元素而不仅仅是一个元素。这个方法返回的是一个 NodeList 的实例。如果没有找到匹配的元素,NodeList 就是空的。

//取得某<div>中的所有<em>元素(类似于 getElementsByTagName("em"))
var ems = document.getElementById("myDiv").querySelectorAll("em");
//取得类为"selected"的所有元素
var selecteds = document.querySelectorAll(".selected");
//取得所有<p>元素中的所有<strong>元素
var strongs = document.querySelectorAll("p strong");

11.2 元素遍历

对于元素间的空格,IE9 及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。这样,就导致了在使用 childNodes 和 firstChild 等属性时的行为不一致。 Element Traversal API 为 DOM 元素添加了以下 5 个属性。

  • childElementCount:返回子元素(不包括文本节点和注释)的个数。
  • firstElementChild:指向第一个子元素;firstChild 的元素版。
  • lastElementChild:指向最后一个子元素;lastChild 的元素版。
  • previousElementSibling:指向前一个同辈元素;previousSibling 的元素版。
  • nextElementSibling:指向后一个同辈元素;nextSibling 的元素版。

利用这些属性就不必担心空白文本节点。

11.3 HTML5

HTML5 规范则围绕如何使用新增标记定义了大量 JavaScript API。其中一些 API 与 DOM 重叠,定义了浏览器应该支持的 DOM 扩展。

11.3.1 与类相关的扩充

getElementsByClassName()方法

方法接收一个参数,即一个包含一或多个类名的字符串,返回带有指定类的所有元素的 NodeList。

//取得所有类中包含"username"和"current"的元素,类名的先后顺序无所谓
var allCurrentUsernames = document.getElementsByClassName("username current");

//取得 ID 为"myDiv"的元素中带有类名"selected"的所有元素
var selected = document.getElementById("myDiv").getElementsByClassName("selected");

classList 属性

这个 classList 属性是新集合类型 DOMTokenList 的实例。这个新类型还定义如下方法

  • add(value):将给定的字符串值添加到列表中。如果值已经存在,就不添加了。
  • contains(value):表示列表中是否存在给定的值,如果存在则返回 true,否则返回 false。
  • remove(value):从列表中删除给定的字符串。
  • toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。

11.3.2 焦点管理

HTML5 也添加了辅助管理 DOM 焦点的功能。

document.activeElement 属性始终会引用 DOM 中当前获得了焦点的元素。元素获得焦点的方式有页面加载、用户输入(通常是 通过按 Tab 键)和在代码中调用 focus()方法。

var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true

document.hasFocus()方法,这个方法用于确定文档是否获得了焦点。

document.hasFocus()方法,这个方法用于确定文档是否获得了焦点。
button.focus();
alert(document.hasFocus()); //true

11.3.3 HTMLDocument的变化

HTML5 扩展了 HTMLDocument,增加了新的功能。尽管这些扩展被写入标准的时间相 对不长,但很多浏览器很早就已经支持这些功能了。

1. readyState 属性

Document 的 readyState 属性有两个可能的值:

  1. loading,正在加载文档;
  2. complete,已经加载完文档。

2. 兼容模式

document.compatMode属性就是为了告诉开发人员浏览器采用了哪种渲染模式。

  1. "CSS1Compat":表示在标准模式
  2. "BackCompat":表示混杂模式
if (document.compatMode == "CSS1Compat"){
    alert("Standards mode");
} else {
    alert("Quirks mode");
}

3. head 属性

HTML5 新增了 document.head 属性,引用文档的<head>元素。所以我们现在引用<head>元素可以这样写:

var head = document.head || document.getElementsByTagName("head")[0];

11.3.4 字符集属性

HTML5 新增了几个与文档字符集有关的属性。

document.charset 属性表示文档中实际使用的字符集,也可以用来指定新字符集。

alert(document.charset); //"UTF-16"
document.charset = "UTF-8";

document.defaultCharset 属性表示根据默认浏览器及操作系统的设置当前文档默认的字符集。

if (document.charset != document.defaultCharset){
    alert("Custom character set being used.");
}

11.3.5 自定义数据属性

HTML5 规定可以为元素添加非标准的属性,但要添加前缀 data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。

<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>

dataset 属性的值是 DOMStringMap 的一个实例,也就是一个名值对儿的映射。用来来访问自定义属性的值。

var div = document.getElementById("myDiv");

//取得自定义属性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;

//设置值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";

11.3.6 插入标记

对于插入大量新 HTML 标记,相对DOM 操作节点而言,使用插入标记的技术,直接插入 HTML 字符串不仅更简单,速度也更快。

1. innerHTML 属性

该属性设置或获取 HTML 语法表示的元素的后代。

2. outerHTML 属性

该属性设置或获取描述元素(包括其后代)的序列化 HTML 片段。

3. insertAdjacentHTML()方法

将指定的文本解析为 Element 元素,并将结果节点插入到 DOM 树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接使用 innerHTML 操作更快。该方法有2个参数。

第一个参数必须是下列值之一:

  • "beforebegin",在当前元素之前插入一个紧邻的同辈元素;
  • "afterbegin",在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;
  • "beforeend",在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;
  • "afterend",在当前元素之后插入一个紧邻的同辈元素。

第二个参数是一个 HTML 字符串串(与 innerHTML 和 outerHTML的值相同)

11.3.7 scrollIntoView()方法

HTML5 最终选择了 scrollIntoView()作为控制页面滚动标准方法。

它可以在所有 HTML 元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。该方法可以接受一个参数,默认值为true表示窗口滚动之后会让调用元素的顶部与视口顶部尽可能平齐

//让元素可见
document.forms[0].scrollIntoView();

实际上,为某个元素设置焦点也会导致浏览器滚动并显示出获得焦点的元素。

11.4 专有扩展(非标准API)

还有很多没有纳入HTML5规范,但是很多浏览器都实现的一些API。

  • document.documentMode: 用来获取文档模式
  • children属性:获取当前元素的元素子节点。
  • contains()方法:用于判断传入的节点是否某个节点后代
  • innerText 属性:读写元素中包含的所有文本内容
  • outerText 属性:读的时候跟innerText保持一致,写的时候不只是替换调用它的元素的子节点,而是会替换整个元素(包括子节点)
  • 滚动相关
    • scrollIntoViewIfNeeded(alignCenter)
    • scrollByLines(lineCount)
    • scrollByPages(pageCount)