《JavaScript高级程序设计(第3版)》第11章 DOM扩展总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010011236/article/details/86552684

11.1、选择符 API

Selectors API 是由 W3C 发起制定的一个标准,致力于让浏览器原生支持 CSS 查询。

11.1.1、querySelector() 方法

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

<div id="myDiv" class="bd" title="body text" lang="en" dir="ltr" my_special_attribute="hello!">测试</div>
<div id="myDiv2" class="bd" style="width:400px;height:400px;background-color:red;">测试2</div>
<script>
  // 返回第一个匹配的元素
  var div = document.querySelector('div');
  // 取得 ID 为 "myDiv" 的元素
  var myDiv = document.querySelector('#myDiv');
  // 取得类为 "bd" 的第一个元素
  var bd = document.querySelector('.bd');

  console.log(div === myDiv);  // true
  console.log(div === bd);     // true

</script>

注意:通过 document 调用 querySelector() 方法时,会在文档元素的范围内查找匹配的元素。而通过 Element 类型调用 querySelector() 方法时,只会在该元素后代元素的范围内查找匹配的元素。

11.1.2、querySelectorAll() 方法

querySelectorAll() 方法接受一个 CSS 选择符作为参数,返回所有匹配的元素,返回的是 NodeList 的实例。如果没找到则返回的 NodeList 为空。

具体来说,返回的值实际上是带有所有属性和方法的 NodeList,而其底层实现则类似与一组元素的快照,而非不断对文档进行搜索的动态查询。这样实例可以避免使用 NodeList 对象通常会引起的大多数性能问题。

// 取得某 <div> 中的所有 <em> 元素
var ems = document.getElementById("myDiv").querySelectorAll("em");

// 取得类为 "selected" 的所有元素
var selecteds = document.querySelectorAll(".selected");

// 取得所有 <p> 元素中的所有 <strong> 元素
var strong = document.querySelector("p strong");

11.1.3、matchesSelector() 方法

为 Element 类型新增的方法 matchesSelector() 方法,该方法接受一个 CSS 选择符,如果调用元素该选择符匹配,则返回 true;否则,返回 false。

<div id="myDiv">测试</div>
<script>
  // 取得 ID 为 "myDiv" 的元素
  var myDiv = document.querySelector('#myDiv');
  // 在 chrome 中进行测试
  console.log(myDiv.webkitMatchesSelector('#myDiv')); // true
</script>

根据不同浏览器的兼容性考虑,可以编写一个包装函数:

function matchesSelector(element, selector) {
    if (element.matchesSelector) {
        return element.matchesSelector(selector);
    } else if (element.msMatchesSelector) {
        return element.msMatchesSelector(selector);
    } else if (element.mozMatchesSelector) {
        return element.mozMatchesSelector(selector);
    } else if (element.webkitMatchesSelector) {
        return element.webkitMatchesSelector(selector);
    } else {
        throw new Error("Not supported.");
    }
}

11.2、元素遍历

注意:对于元素间的空格,IE9 及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。

为方便元素遍历,Element Traversal API 为 DOM 添加了一下 5 个属性:

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

利用这些属性不必担心空白文本节点,从而可以更方便的查找 DOM 元素。

<ul id="item">
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
</ul>
<script>
    var item = document.querySelector('#item');

    console.log(item.childNodes.length);  // 7
    console.log(item.childElementCount);  // 3
</script>

11.3、HTML5

11.3.1、与类相关的扩展

1.getElementsByClassName() 方法

getElementsByClassName() 方法接受一个参数,即一个包含一或多个类名的字符串,返回带有指定类的所有元素的 NodeList。传入多个类名时,类名的先后顺序不重要。

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

2.classList 属性

在操作类名时,需要通过 className 属性添加、删除和替换类名。对于元素中有多个类名时,使用该方法替换、删除类名时比较麻烦。而 HTML5 为所有元素添加了 classList 属性,该属性是新集合类型 DOMTokenList 的实例,该实例有如下方法:

  • add(value):将给定的字符串添加到列表中。如果已存在,则不添加。
  • contains(value):表示列表中是否存在给定的值,如果存在则返回 true,否则返回 false。
  • remove(value):从列表中删除给定的字符串。
  • toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
<div id="cbm" class="ceshi cshi bm">测试3</div>
<script>
    var cbm = document.getElementById('cbm');
    console.log(cbm.classList); // DOMTokenList(3) ["ceshi", "cshi", "bm", value: "ceshi cshi bm"]
    console.log(cbm.classList.toggle('bm'));
    console.log(cbm.classList); // DOMTokenList(2) ["ceshi", "cshi", value: "ceshi cshi"]
</script>

11.3.2、焦点管理

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

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

11.3.3、HTMLDocument 的变化

1.readyState 属性

readyState 属性在 HTML5 标准中,Document 的 readyState 属性有两个可能的值:

  • loading,正在加载文档;
  • complete,已经加载完文档。

使用 document.readyState 的最恰当方式,就是通过它来实现一个指示文档已经加载完成的指示器。

2.兼容模式

document 的 compatMode 属性告诉开发人员浏览器采用哪种渲染模式。

标准模式:document.compatMode == "CSS1Compat"

混杂模式:document.compatMode == "BackCompat"

console.log(document.compatMode); // chrom : "CSS1Compat"

3.head 属性

H5 中新增的 document.head 属性引用文档的 <head> 元素。

11.3.4、字符集属性

H5 中新增加的有关字符集的属性:

  • charset:表示文档中实际使用的字符集
  • defaultCharset:表示默认浏览器及操作系统的设置,当前文档默认的字符集类型应该是什么。

11.3.5、自定义数据属性

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

添加了自定义属性之后,可以通过 dataset 属性来访问自定义属性的值。dataset 属性也就是一个名值对儿映射。在这个映射中,每个 data-name 形式的属性都会有一个对应的属性,只不过属性名没有 data- 前缀(比如,自定义属性是 data-myname,那映射中对应的属性就是 myname)。

<div id="myDiv" data-appId="12345" data-myname="Nicholas">测试</div>
<script>
    var myDiv = document.getElementById('myDiv');

    console.log(myDiv.dataset.appid);  //在 chrome 和 firefox 中小写有效,结果为 '12345'
    console.log(myDiv.dataset.myname); // 'Nicholas'
</script>

11.3.6、插入标记

1.innerHTML 属性

在读模式下,innerHTML 属性返回与调用元素所有子元素(包括元素、注释和文本节点)对应的 HTML 标记

在写模式下,innerHTML 的值会被解析为 DOM 子树,替换调用元素原来的所有子节点。

<div id="container">
    <p>This is a <strong>paragraph</strong> with a list following is.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>
<script>
    var container = document.getElementById('container');
    console.log(container.innerHTML);
    container.innerHTML = 'Hello World!';
    console.log(container.innerHTML);
</script>

2.outerHTML 属性

在读模式下,outerHTML 返回调用它的元素及所有子节点的 HTML 标签。

在写模式下,outerHTML 会根据指定的 HTML 字符串创建新的 DOM 子树,然后用这个 DOM 子树 完全替换调用元素。

<div id="container">
    <p>This is a <strong>paragraph</strong> with a list following is.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>
<script>
    var container = document.getElementById('container');
    console.log(container.outerHTML);
    container.outerHTML = "<p>strong boy.</p>"; //直接取代<div id="container"></div>
</script>

3.insertAdjacentHTML() 方法

插入标记方法 insertAdjacentHTML(),该方法接受两个参数:插入位置要插入的 HTML 文本。第一个参数必须是下列值之一:

  • "beforebegin",在当前元素之前插入一个紧邻的同辈元素;
  • "afterend",在当前元素之后插入一个紧邻的同辈元素。
  • "afterbegin",为当前元素添加一个子元素(位于子元素 DOM 中第一个位置);
  • "beforeend",为当前元素添加一个子元素(位于子元素 DOM 中最后一个位置);
<div id="container">
    <p>This is a <strong>paragraph</strong> with a list following is.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>
<script>
    // 作为前一个同辈元素插入
    container.insertAdjacentHTML('beforebegin', '<p>this is a strong boy.</p>');
    // 作为后一个同辈元素插入
    container.insertAdjacentHTML('afterend', '<p>end</p>');
    // 作为第一个子元素插入
    container.insertAdjacentHTML('afterbegin', '<p>afterbegin</p>');
    // 作为最后一个子元素插入
    container.insertAdjacentHTML('beforeend', '<p>beforeend</p>');
</script>

4.内存与性能问题

在删除带有事件处理程序或引用了其他 JavaScript 对象子树时,就可能导致内存占用问题。

最好手工删除要被替换的元素的所有事件处理程序和的 JavaScript 对象属性。

11.3.7、scrollIntoView() 方法

scrollIntroView() 可以在所有 HTML 元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。如果给这个方法传入 true 作为参数,或者不传入任何参数,那么窗口滚动之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入 false 作为参数,调用元素会尽可能全部出现在视口中,(可能的话,调用元素的底部会与视口底部平齐。)

11.4、专有扩展

11.4.1、文档模式

11.4.2、children 属性

children 属性,该属性是 HTMLCollection 的实例,只包含元素中同样还是元素的子节点。除此之外,children 属性与 childNodes 没有什么区别,即在元素只包含元素子节点时,这两个属性的值相同。

11.4.3、contains() 方法

测试某个节点是不是另一个节点的后代,可以使用 contains() 方法。

调用 contains() 方法的应该是祖先节点,也就是搜索开始的节点,这个方法接受一个参数,即要检测的后代节点。如果被检测的节点是后代节点,该方法返回 true;否则,返回 false。

DOM Level 3 中的 compareDocumentPosition() 用于确定两个节点间的关系,返回一个表示该关系的位掩码。

console.log(document.documentElement.compareDocumentPosition(document.body));  // 4+16=20

11.4.4、插入文本

1.innerText 属性

innerText 属性可以操作元素中包含的所有文本内容包括子文档树中的文本

注意:设置 innerText 永远只会生成当前节点的一个子文本节点,而为了确保只生成一个子文本节点,就必须要对文本进行 HTML 编码。利用这一点,可以通过 innerText 属性过滤掉 HTML 标签。

2.outerText 属性

outerText 属性不只是替换调用它的元素的子节点,而是会替换整个元素(包括子节点)。

11.4.5、滚动

参考文献

[1]《JavaScript高级程序设计(第3版)》

猜你喜欢

转载自blog.csdn.net/u010011236/article/details/86552684