JS知识点梳理(8)-DOM2级遍历和范围

DOM 遍历

“DOM2 级遍历和范围”模块定义了 2 个用于遍历 DOM 结构的类型:NodeIteratorTreeWalker。它们都是基于给定的起点对 DOMM 结构执行深度优先的遍历操作。

NodeIterator

使用document.createNodeIterator(root,whatToShow,filter)方法创建.

  • root,创建NodeIterator时指定的根节点,即搜索的起点
  • whatToShow,表示要呈现的 Node 类型,由常量构成的位掩码。不匹配的节点被跳过。该参数的值以常量形式在 NodeFilter 类型中定义,如下所示
    • NodeFilter.SHOW_ALL:显示所有类型的节点
    • NodeFilter.SHOW_ELEMENT:显示元素节点
    • NodeFilter.SHOW_TEXT:显示文本节点
    • NodeFilter.SHOW_DOCUMENT:显示文档节点
    • NodeFilter.SHOW_COMMENT:显示注释节点
  • filter,用来指定自定义的 NodeFilter 对象,或者指定一个功能类似节点过滤器的函数。每个 NodeFilter 对象只有一个方法,即acceptNode(),如果应该访问给定节点,该方法返回NodeFilter.FILTER_ACCEPT,如果不应该访问给定节点,则返回NodeFilter.FILTER_SKIP,如果不指定,则传入null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 // 只显示<p>元素的节点迭代器
var filterObj = {
acceptNode: function (node) {
return node.nodeType === Node.ELEMENT_NODE &&
node.tagName.toLowerCase() === "p"
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP;
},
};
var iterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ALL,
filterObj
);


var filterFn = function (node) {
console.log("filterFn node", node);
return node.tagName.toLowerCase() === "p"
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP;
};

var iterator2 = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT,
filterFn
);

NodeIterator类型有 2 个方法

  • nextNode(),返回下一个节点,不存在返回null
  • previousNode(),返回前一个节点,不存在返回null

TreeWalker

TreeWalker 是 NodeIterator 的更高级版本。使用document.createTreeWalker(root,whatToSHow,filter),参数同doucument.createNodeIterator()方法相同.但 filter 可以返回的值不同。可以使用NodeFilter.FILTER_REJECT

  • 在使用NodeIterator对象时,NodeFilter.FILTER_REJECTNodeFilter.FILTER_SKIP的作用相同

  • 在使用TreeWalker对象时,NodeFilter.FILTER_SKIP会跳过相应节点并前进到子树的下一个节点,而NodeFilter.FILTER_REJECT会跳过相应节点以及该节点的整个子树。
    除了包含nextNode()previousNode()方法外,还提供了用于不同方向上的遍历方法

  • parentNode(),遍历到当前节点的父节点

  • firstChild(),遍历到当前节点的第一个子节点

  • lastChild(),遍历到当前节点的最后一个子节点

  • nextSibling(),遍历到当前节点的下一个同辈节点

  • previousSibling(),遍历到当前节点的上一个同辈节点

DOM 范围

“DOM2 级遍历和范围”中定义了范围(Range)接口,通过该接口可以选择文档中的一个区域,而不必考虑节点的界限。可以Document对象中的creanteRange()方法创建 Range。每一个范围由一个 Range 类型的实例表示

Range 属性

  • startContainer,包含范围起点的节点
  • startOffset,范围在startContainer中起点的偏移量
  • endContainer,包含范围终点的节点
  • endOffset,范围在endContainer中终点的偏移量
  • commonAncestorContainer,包含整个startContainerendContainer的共同的祖先节点

Range 方法

简单的范围 定位方法

  • selectNode(node),范围设置为包含整个给定的 node 节点(包括节点本身及其内容),此时范围的startContainerendContainer属性是 node 节点的父节点
  • seletNodeContents(node),范围设置为包含给定 node 节点的内容。此时范围的startContainerendContainer属性就是给定 node 节点,startOffset为 0,endOffset为 node 节点的字符数或子节点个数

复杂的范围 定位方法

  • setStart(startNode, startOffset),设置范围的起始位置,参照节点startNode变成范围startContainer属性的值,偏移量startOffset变成范围startOffset属性的值。
  • setend(endNode,endOffset),设置范围的终点。

范围 编辑方法

  • deleteContents(),从文档中移除 范围中的内容
  • extractContents(),把范围中的内容从文档移动到一个文档片段中
  • cloneContents(),返回一个包含范围中内容的文档片段
  • insertNode(newNode),在范围的起始位置插入给定节点
  • cloneRange(),复制范围,返回一个克隆的范围 对象。
  • detach(),清理范围,在使用完范围后,最后调用detach()方法,以便从创建范围的文档中分离处该范围,同时要解除对范围的引用(设置为 null),从而回收内存