JavaScript高级程序设计笔记 15

第15章 DOM 扩展

1. 概述

  • DOM 扩展的两个主要标准:Selectors API 与 HTML5(另有较小的 Element Traversal 规范)。
  • 目的:将实践中已广泛使用的专有扩展标准化。

2. Selectors API(选择符 API)

  • 核心:让浏览器原生支持 CSS 查询,性能远超 JavaScript 实现的解析器。
  • Level 1 的两个核心方法(Document 和 Element 类型上均可用):

2.1 querySelector()

  • 接收一个 CSS 选择符,返回匹配的第一个元素,没有则返回 null。
  • 在 Document 上调用从文档元素开始搜索;在 Element 上调用则从当前元素的后代中搜索。
  • 示例:
    document.querySelector('#myDiv');
    element.querySelector('.selected');
    

2.2 querySelectorAll()

  • 接收一个 CSS 选择符,返回所有匹配的节点(NodeList 静态实例,是“快照”而非“实时”查询)。
  • 示例:
    document.querySelectorAll('p strong');
    

2.3 matches() / matchesSelector()

  • Selectors API Level 2 规范新增,在 Element 类型上可用。
  • 接收一个 CSS 选择符,如果元素匹配则该选择符返回 true,否则返回 false。
  • 可用于检测元素是否会匹配 querySelector() 方法的查询条件。

3. 元素遍历(Element Traversal API)

  • API:为 DOM 元素添加了 5 个属性,只遍历元素节点,忽略文本节点和注释节点。
    • childElementCount:返回子元素数量。
    • firstElementChild / lastElementChild:指向第一个 / 最后一个子元素。
    • previousElementSibling / nextElementSibling:指向前一个 / 后一个同胞元素。

4. HTML5 DOM 扩展

  • 定义了浏览器应当支持的 DOM 扩展。

4.1 CSS 类扩展

  • getElementsByClassName() 方法:接收一个或多个类名字符串,返回包含指定类的所有元素的 NodeList。
  • classList 属性:所有元素都有的属性,是 DOMTokenList 的实例,提供了便捷的类名操作方法。
    • add(value):添加类名。
    • contains(value):检查类名是否存在。
    • remove(value):移除类名。
    • toggle(value):如果存在则删除,否则添加。

4.2 焦点管理

  • document.activeElement:始终引用当前获得焦点的 DOM 元素。
  • document.hasFocus():返回布尔值,表示文档是否拥有焦点。

4.3 HTMLDocument 扩展

  • readyState 属性:
    • loading:文档正在加载。
    • complete:文档加载完成。
  • compatMode 属性:告诉开发者浏览器处于什么渲染模式。
    • CSS1Compat:标准模式。
    • BackCompat:混杂模式。
  • head 属性:document.head 直接指向文档的 <head> 元素。

4.4 字符集属性

  • document.characterSet 属性表示文档实际使用的字符集,如 'UTF-16'

4.5 自定义数据属性

  • 前缀为 data- 的自定义属性(如 data-id="123")。
  • 通过元素的 dataset 属性访问,dataset 属性是一个 DOMStringMap 实例,包含一组键值对。

4.6 插入标记

  • innerHTML 属性:
    • 读取时返回元素所有后代的 HTML 字符串。
    • 写入时根据提供的字符串创建新的 DOM 子树,并替换原有子节点。
  • outerHTML 属性:
    • 读取时返回调用它的元素及所有后代元素的 HTML 字符串。
    • 写入时调用它的元素会被传入的 HTML 字符串生成的 DOM 子树取代。
  • insertAdjacentHTML() / insertAdjacentText() 方法:
    • 接收两个参数:插入位置和要插入的 HTML 或文本。
    • 位置参数:'beforebegin', 'afterbegin', 'beforeend', 'afterend'
  • 内存与性能问题
    • 使用 innerHTML 和 outerHTML 时,需要手动删除被替换元素上的事件处理程序和 JavaScript 对象属性,避免内存泄漏。
    • 批量操作时推荐先构建一个独立的 DOM 树(如使用 createDocumentFragment()),最后再一次性插入,以减少浏览器重排(Reflow)和重绘(Repaint)。

4.7 scrollIntoView() 方法

  • 存在于所有 HTML 元素上,可以滚动浏览器窗口使元素进入视口。

5. 专有扩展

  • 尽管 Selectors API 和 HTML5 两个规范已涵盖大量 DOM 扩展,但一些浏览器的专有扩展仍然存在。
  • children 属性:与 childNodes 类似,但 children 只包含元素节点,是 HTMLCollection 实例。
  • contains() 方法:判断一个节点是不是另一个节点的后代。

6. 常见面试题速查

  1. querySelector 和 querySelectorAll 返回的集合是“实时的”还是“静态的”?
    → querySelectorAll 返回一个静态的 NodeList“快照”,不会随文档更新。而 getElementsByClassName 等方法返回的是实时的 HTMLCollection。

  2. classList 相比 className 有什么优势?
    → classList 提供了 add、remove、toggle 和 contains 等便捷方法,避免了通过字符串拼接修改类名的繁琐和出错风险。

  3. 如何安全地使用 innerHTML?
    → 永远不要将用户输入的字符串直接赋值给 innerHTML。在插入任何不可信的字符串之前,必须进行转义(例如,将 < 转义为 &lt;),以防止 XSS 攻击。

  4. 如何判断一个元素是否匹配某个 CSS 选择器?
    → 使用 element.matches(selector) 方法。

  5. 页面加载状态可以通过什么属性判断?
    → 通过 document.readyState 属性,值为 'loading''complete'

  6. 如何获取 <head> 元素?
    → 使用 document.head 属性。

  7. Element Traversal API 解决了什么问题?
    → 解决了空白文本节点可能干扰遍历结果的问题,因为它提供的属性只返回元素节点。

  8. 什么是 dataset?
    → dataset 是用于访问元素上自定义数据属性(data-*)的接口。

posted @ 2024-04-25 14:24  Li_pk  阅读(7)  评论(0)    收藏  举报