学习 TreeWalker api 并与普通遍历 DOM 方式进行比较
介绍 TreeWalker
TreeWalker 是 JavaScript 中用于遍历 DOM 树的一个接口。允许你以灵活的方式在 DOM 树中进行前向和后向遍历,包括访问父节点、子节点和兄弟节点。适用于处理复杂的 DOM 操作:在遍历过程中进行添加、删除或修改节点的操作,并继续遍历。
与普通的 for 循环 + querySelector 相比灵活性更高。执行速度方面,在 DOM 超过一定复杂度的情况下,TreeWalker 更快,后面会举例说明。
实践
创建 TreeWalker
可以使用 document.createTreeWalker 方法来创建一个 TreeWalker 对象。这个方法接受四个参数:
root:要遍历的根节点。whatToShow(可选):一个整数,表示要显示的节点类型。默认值是NodeFilter.SHOW_ALL,表示显示所有节点。filter(可选):一个NodeFilter对象,用于自定义过滤逻辑。entityReferenceExpansion(可选):一个布尔值,表示是否展开实体引用。这个参数在现代浏览器中通常被忽略,因为实体引用在HTML中很少使用
const walker = document.createTreeWalker(
document.body,//.root
NodeFilter.SHOW_ELEMENT,// whatToShow(可选)
null,// filter(可选)
false //entityReferenceExpansion(可选)
)
NodeFilter.SHOW_ELEMENT 表示显示元素节点。
节点类型
NodeFilter 有 12 种节点类型,和 Node 接口的节点类型一一对应;
| NodeFilter | Node.prototype |
|---|---|
| SHOW_ELEMENT:显示元素节点。 | 1: ELEMENT_NODE |
| SHOW_ATTRIBUTE:显示属性节点(在HTML 中不常用)。 | 2: ATTRIBUTE_NODE |
| SHOW_TEXT:显示文本节点。 | 3:TEXT_NODE |
| SHOW_CDATA_SECTION:显示CDATA 节点(在HTML 中不常用)。 | 4:CDATA_SECTION_NODE |
| SHOW_ENTITY_REFERENCE:显示实体引用节点(在HTML 中不常用)。 | 5: ENTITY_REFERENCE_NODE |
| SHOW_ENTITY:显示实体节点(在HTML 中不常用)。 | 6 : ENTITY_NODE |
| SHOW_PROCESSING_INSTRUCTION:显示处理指令节点。 | 7: PROCESSING_INSTRUCTION_NODE |
| SHOW_COMMENT:显示注释节点。 | 8:COMMENT_NODE |
| SHOW_DOCUMENT:显示文档节点。 | 9:DOCUMENT_NODE |
| SHOW_DOCUMENT_TYPE:显示文档类型节点。 | 10: DOCUMENT_TYPE_NODE |
| SHOW_DOCUMENT_FRAGMENT:显示文档片段节点。 | 11 : DOCUMENT_FRAGMENT_NODE |
| SHOW_NOTATION:显示符号节点(在HTML 中不常用)。 | 12 : NOTATION_NDE |
NodeFilter.SHOW_ALL 表示显示所有类型节点,这和遍历节点的 childNodes 一样,childNodes 会把该节点下的所有类型的子节点遍历出来。而节点的 children 就只遍历元素节点。
自定义过滤器
可以通过传递一个 NodeFilter 对象来实现自定义的过滤逻辑。NodeFilter 对象有一个 acceptNode 方法,该方法返回一个常量来决定是否接受节点:
- NodeFilter.FILTER_ACCEPT:接受节点。
- NodeFilter.FILTER_REJECT:拒绝节点及其子节点。
- NodeFilter.FILTER_SKIP:跳过节点,但继续遍历其子节点。
const filter = {
acceptNode: function (node){
if (node.tagName=== "DIV"){
return NodeFilter.FILTER_ACCEPT;
}else {
return NodeFilter.FILTER_SKIP;
}
},
};
const walker = document.createTreeWalker(
document.body,
NodeFilter.SH