先序遍历DOM树的5种方法
DOM树由文档中的所有节点(元素节点、文本节点、注释节点等)所构成的一个树结构,DOM树的解析和构建是浏览器要实现的关键功能。既然DOM树是一个树结构,那么我们就可以使用遍历树结构的相关方法来对DOM树进行遍历,同时DOM2中的"Traversal"模块又提供了两种新的类型,从而可以很方便地实现DOM树的先序遍历。
注:本文中的5种方法都是对DOM的先序遍历方法(深度优先遍历),并且只关注Element类型。
1. 使用DOM1中的基础接口,递归遍历DOM树
DOM1中为基础类型Node提供了一些api,通过这些api可以完成一些基础的DOM操作。使用递归遍历DOM树的代码比较简单,核心思想就是先处理当前节点,然后再从左到右递归遍历子节点,代码如下:
- /**
- * 使用递归的方式先序遍历DOM树
- * @param node 根节点
- */
- function traversal(node){
- //对node的处理
- if(node && node.nodeType === 1){
- console.log(node.tagName);
- }
- var i = 0, childNodes = node.childNodes,item;
- for(; i < childNodes.length ; i++){
- item = childNodes[i];
- if(item.nodeType === 1){
- //递归先序遍历子节点
- traversal(item);
- }
- }
- }
2. 使用DOM1的基础接口,迭代遍历DOM树
与第1种方法不同,这一次使用迭代的方法遍历DOM树。使用迭代遍历DOM树相对复杂一些,关键点在于使用一个栈来维护节点的访问路径,当处理完当前节点时,先把该节点的第一个Element子节点作为下一次循环的根节点,并且按照从右到左的顺序,将当前节点的其他子元素节点压入栈中。如果当前节点没有一个Element子节点,则从栈中弹出一个Element节点作为下一次循环的根节点,直到取不到根节点为止。代码如下:
- /**
- * 使用迭代的方式先序遍历DOM树
- * @param node 根节点
- */
- function traversalIteration(node){
- var array = [], i = 0,k = 0,elementCount = 0, len = 0, childNodes,item;
- while(node != null){
- console.log(node.tagName);
- childNodes = node.childNodes;
- len = node.childNodes.length;
- elementCount = 0;
- if(len > 0){
- for(i = 0; i < len; i++){
- item = childNodes[i];
- if(item.nodeType === 1){
- elementCount++;
- node = item;
- break;
- }
- }
- for(k = len -1 ; k > i; k--){
- item = childNodes[k];
- if(item.nodeType == 1){
- elementCount++;
- array.push(item);
- }
- }
- if(elementCount < 1){
- node = array.pop();
- }
- }else{
- node = array.pop();
- }
- }
- }
3. 使用DOM扩展的Element Traversal API,递归遍历DOM树
DOMElement Traversal API提供了几个方便DOM遍历的接口,从而可以更加方便地取得一个节点的Element子节点。在《DOM扩展:DOM API的进一步增强[总结篇-上]》的第2节介绍了DOM扩展的Element Traversal API。代码如下:
- /**
- * 使用DOM扩展的Traversal API提供的新的接口先序遍历DOM树
- * @param node 根节点
- */
- function traversalUsingTraversalAPI(node){
- if(node && node.nodeType === 1){
- console.log(node.tagName);
- }
- var i = 0,len = node.childElementCount, child = node.firstElementChild;
- for(; i < len ; i++){
- traversalUsingTraversalAPI(child);
- child = child.nextElementSibling;
- }
- }
4. 使用NodeIterator
DOM2的"Traversal"模块提供了NodeIterator类型,使用它可以很方便地实现DOM树的先序遍历,《JavaScript高级程序设计第三版》的12.3.1节介绍了这个类型,我们这里直接给出代码如下:
- /**
- * 使用DOM2的"Traversal"模块提供的NodeIterator先序遍历DOM树
- * @param node 根节点
- */
- function traversalUsingNodeIterator(node){
- var iterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT,null,false);
- var node = iterator.nextNode();
- while(node != null){
- console.log(node.tagName);
- node = iterator.nextNode();
- }
- }
5. 使用TreeWalker
TreeWalker类型可以说是NodeIterator类型的增强版,《JavaScript高级程序设计第三版》的12.3.2节介绍了这个类型,我们这里也直接给出代码如下:
- /**
- * 使用DOM2的"Traversal"模块提供的TreeWalker先序遍历DOM树
- * @param node 根节点
- */
- function traversalUsingTreeWalker(node){
- var treeWalker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT,null,false);
- if(node && node.nodeType === 1){
- console.log(node.tagName);
- }
- var node = treeWalker.nextNode();
- while(node != null){
- console.log(node.tagName);
- node = treeWalker.nextNode();
- }
- }
欢迎小伙伴评论交流~~
先序遍历DOM树的5种方法的更多相关文章
- JavaScript 算法应用: 遍历DOM树的两种方式
1 常见的DOM树结构: 2 DOM数遍历有两种方式: 3 广度优先代码: 4 深度优先遍历代码
- 函数遍历DOM树
//获取页面中的根节点--根标签 var root=document.documentElement;//html //函数遍历DOM树 //根据根节点,调用fn的函数,显示的是根节点的名 ...
- jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别
http://www.poluoluo.com/jzxy/201312/253059.html 在这个sprint中,因为要写前端UI,所以用到了jQuery,但是jQuery在向上遍历DOM树的AP ...
- 拷贝和遍历DOM树
一.浅拷贝: 拷贝就是复制,就相当于把一个对象中的所有内容,复制一份给另一个对象,直接复制, 或者说,就是把一个对象的地址给了另外一个对象,他们的指向相同,两个对象之间有相同的属性或者方法,都可以使用 ...
- JS高级---遍历DOM树
遍历DOM树 第一个函数: 给我根节点, 我会找到所有的子节点: forDOM(根节点) 获取这个根节点的子节点 var children=根节点的.children 调用第二个函数 第二个 ...
- Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解
Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...
- JQuery遍历json数组的3种方法
这篇文章主要介绍了JQuery遍历json数组的3种方法,本文分别给出了使用each.for遍历json的方法,其中for又分成两种形式,需要的朋友可以参考下 一.使用each遍历 $(functio ...
- Java遍历List集合的三种方法
Java遍历List集合的三种方法 List<String> list = new ArrayList<String>(); list.add("aaa") ...
- (转载)Java中如何遍历Map对象的4种方法
在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...
随机推荐
- 11.20 正则表达式 断言(?=exp)
今天看源代码,研究了一下qz写的这个方法: // 添加逗号分隔,返回为字符串 comma: function(length) { ) length = ; var source = ('' + thi ...
- labellmg的使用
---恢复内容开始--- 在powershell环境下进入到labelImg解压后的文件,我这里是D:\labelImg-master\labelImg-master 执行命令: pyrcc5 -o ...
- Autel MaxiTPMS TS601 Wireless TPMS Sensor Reset Relearn Activate Programming Tool
Why Choose Autel TPMS TS601? MaxiTPMS TS601 is a TPMS tool with highest performance in the world. It ...
- 洛谷P1576||最小花费||dijkstra||双向建边!!
题目描述 在n个人中,某些人的银行账号之间可以互相转账.这些人之间转账的手续费各不相同.给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元. 数据范 ...
- Non-decreasing Array LT665
Given an array with n integers, your task is to check if it could become non-decreasing by modifying ...
- ----Arrow functions----
Arrow functions Arrow functions表达式相比函数表达式有更短的语法,没有自己的this.argument.super或者new.target. 1.语法规则: 基础语法: ...
- zookeeper名字服务
10.12.67.31 #!/bin/shmkdir -p /data/zk-install/cd /data/zk-install/wget -q -O ons_agent-1.0.5.tar.gz ...
- java36
1.Main public static void main(String [ ] args) public:被jvm调用的方法,权限要足够大 static:被jvm调用的方法,不需要创建对象,直接用 ...
- tensorflow学习之(十一)将python代码写入文件
#save to file import tensorflow as tf import numpy as np ##(1)Save to file 把相关变量存储到文件中 #remember to ...
- 如何方便的在windows测试python程序
听说python的网页抓取模块很强大,我想试试看看能给我的网络优化工作带来什么大的帮助,于是跟随廖雪峰老师开始学习python(地址查看),因为我用的是window系统,这就给程序的测试带来了很多麻烦 ...