先序遍历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都 ...
随机推荐
- UEFI EVENT 全解
Event和Timer在UEFI当中是怎么实现的以及原理,我们先从Timer开始,然后细细的拨开隐藏在底层的实现. 先说Timer,那什么是Timer呢?其实在中文里面我们把它叫做定时/计数器,但是我 ...
- ubuntu18.04微信小程序学习笔记
安装微信小程序开发工具 安装 https://github.com/cytle/wechat_web_devtools 创建快捷方式 sudo nautilus //在/usr/share/appli ...
- Google弃用HttpClient 而推荐使用HttpURLConnection的原因
因为兼容性问题,谷歌不愿意维护HttpClient,而使用HttpURLConnection HttpURLConnection的API包小而简便,更适合安卓 HttpURLConnection能够提 ...
- mysql设置存储中文变成问号或者乱码
技术交流群: 816227112 问题: 解决办法: 修改my.ini 如果是my-default.ini 要重命名成my.ini 要注意顺序,有可能服务启动不起来 [mysqld] charact ...
- my new blog
博客迁移至: https://www.dboop.com/
- Solved: RDP Disconnected – Error Code 2825 mremote
- python3 第三十章 - 内置函数之Dictionary相关
Python字典包含了以下内置函数: 序号 函数及描述 实例 1 len(dict)计算字典元素个数,即键的总数. >>> dict = {'Name': 'cnblogs', 'A ...
- [Ionic] Error: No provider for Http! Error: No provider for Http!
1. 打开src/app/app.module.ts 2. 在最上面导入 import{HttpModule} from '@angular/http'; 3. 在imports块中加入:HttpMo ...
- tomcat连接常用数据库的用法
一.用于数据库连接的术语: JDBC:(Java database connectivity)是基于java数据访问技术的一个API通过客户端访问服务器的数据库,是一个面向关系型数据库并提供一种方法查 ...
- python语法之正则
1.正则表达式是用来干嘛的? 用来匹配字符串的 ,其中正则是意思是模糊匹配. 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通 ...