DOM 元素的循环遍历
博客地址:https://ainyi.com/89
获取 DOM 元素的几种方式
get 方式:
- getElementById
- getElementsByTagName
- getElementsByClassName
- getElementsByName
返回类型 HTMLCollection[]
query 方式:
- querySelector
- querySelectorAll
返回类型 NodeList[]
获取 dom 元素的详细介绍:https://ainyi.com/31
获取元素
首先用两种方式获取元素
let a = document.getElementsByClassName('title')
let b = document.querySelectorAll('.title')
一般循环
get 方式
get 方式获取的 dom 元素,仅可使用for-in、for-of、for循环
for(let key in a) {
console.log(a[key])
}
// dom
// ...(每个dom元素)
// length(集合长度)
// ƒ item() { [native code] }
// ƒ namedItem() { [native code] }
其中:
ƒ item() { [native code] }
可通过 a.item(index) 获取 dom 元素,类似 a[index]
ƒ namedItem() { [native code] }
可通过 a.namedItem('popo') 获取 name 属性为 'popo' 的 dom 元素(若多个元素有相同的 name 属性,返回第一个)
for-of、for 循环可获取每个 dom 元素:
for(let val of a) {
console.log(val)
}
// dom
// ...(每个dom元素)
for(let i = 0; i < a.length; i++) {
console.log(a[i])
}
// dom
// ...(每个dom元素)
query 方式
query 方式获取的 dom 元素,可使用forEach、for-in、for-of、for循环
forEach、for-of、for 循环的结果无差别
但 for-in 相比 get 方式 的 for-in,循环得出的结果稍有不同
for(let key in b) {
console.log(b[key])
}
// dom
// ...(每个dom元素)
// length(集合长度)
// ƒ item() { [native code] }
// ƒ entries() { [native code] }
// ƒ forEach() { [native code] }
// ƒ keys() { [native code] }
// ƒ values() { [native code] }
与 get 方式的 for-in 相比,少了 ƒ namedItem() { [native code] },多了 Object 的几个方法
这说明,query 方式获取的 dom 元素集合,可执行 Object 对应的方法,但没有 namedItem() 方法
ES6 转换普通数组
ES6 提供了 Array.from() 方法可将这些集合转换成普通数组,这样就可以享用数组的各种方法了
let array = Array.from(a)
深度遍历
节点树的几个属性
- childElementCount:返回子元素(不包括文本节点和注释)的数量
- parentNode:ele 的父节点
- childNodes:ele 的所有的直接子节点
- nextSibling:ele 的下一个同辈节点
- previousSibling:ele 的上一个同辈节点
因为 childNodes 包含看不见的空格文本,还有注释等内容,所以使用起来不是太方便
因此,js 又重新引入了元素树的概念。这个在我们实际应用中,用的比较普遍
元素树:仅仅包含元素节点的树结构,不是一颗新树,尽是节点数的子集
为元素新增了下面几个属性:
- parentElement:节点的父元素
- children:返回节点的所有子元素
- firstElementChild:第一个直接子元素
- lastElementChild:最后一个直接子元素
- previousElementSibling:ele 的前一个兄弟元素
- nextElementSibling:ele 的下个兄弟元素
一般来说,区别元素节点,属性节点,文本节点的通用方式是判断该节点的 nodeType
常见的几种 nodeType:
元素节点:1,
属性节点:2,
文本节点:3,
注释节点:8,
...
遍历直接子级元素
假设 html 如下,要遍历出 div 中的所有直接子级的元素节点:
<div id="list">
<p>hello</p>
<span>world</span>
<em>cookieParse()</em>
</div>
用 firstChild,lastChild 进行元素遍历
let list = document.getElementById('list')
let child = list.firstChild
console.log(list.nextSibling)
while(child != list.lastChild) {
if(child.nodeType === 1) {
console.log( child )
}
child = child.nextSibling
}
使用 firstElementChild,nextElementSibling
let list = document.getElementById('list')
let child = list.firstElementChild
while(child) {
console.log( child )
child = child.nextElementSibling
}
深度优先遍历
遍历所有节点
深度优先遍历:当同时有兄弟节点和子节点的时候,总是优先遍历子节点
function getChildren(parent) {
// 如果当前节点是元素节点,输出当前元素
parent.nodeType === 1 && console.log(parent);
// 获得父节点的所有直接子节点
let children = parent.childNodes
// 遍历 children 中每个节点
for(let i = 0, len = children.length; i<len; i++) {
// 对当前子节点递归
getChildren(children[i])
}
}
getChildren(document.body)
需要注意的是:递归的运行效率没有迭代的运行效率高,一般都需要把递归的循环优化成迭代的循环
所以上面递归算法可以进一步优化
优化深度优先遍历
使用 NodeIterator 对象,可以对 DOM 树进行深度优先的搜索
创建 NodeIterator 对象,需要使用 document 对象的 createNodeIterator 方法,该方法接收四个参数:
- root:搜索开始的节点
- whatToShow:一个数值代码,表示哪些节点需要搜索
- filter:NodeFilter 对象,决定忽略哪些节点
- entityReferenceExpansion:布尔值,表示是否需要扩展实体引用
whatToShow 参数:
| 参数 | 意义 |
|---|---|
| NodeFilter.SHOW_ALL | 显示所有类型的节点 |
| NodeFilter.SHOW_ELEMENT | 显示元素节点 |
| NodeFilter.SHOW_ATTRIBUTE | 显示特性节点 |
| NodeFilter.SHOW_TEXT | 显示文本节点 |
| NodeFilter.SHOW_CDATA_SECTION | 显示CDATA节点。对HTML页面无用 |
| NodeFilter.SHOW_ENTITY_REFERENCE | 显示实体引用节点 |
| NodeFilter.SHOW_ENTITYE | 显示实体节点 |
| NodeFilter.SHOW_PROCESSING_INSTRUCTION | 显示处理指令节点 |
| NodeFilter.SHOW_COMMENT | 显示注释节点 |
| NodeFilter.SHOW_DOCUMENT | 显示元档节点 |
| NodeFilter.SHOW_DOCUMENT_TYPE | 显示文档类型节点 |
| NodeFilter.SHOW_DOCUMENT_FRAGMENT | 显示文档片段节点 |
| NodeFilter.SHOW_SHOW_NOTATION | 显示符号节点 |
| NodeFilter.SHOW_DOCUMENT_TYPE | 显示文档类型节点 |
优化如下:
function getChildren(parent){
// 获取 NodeIterator 对象
let t = document.createNodeIterator(parent, NodeFilter.SHOW_ELEMENT, null, false)
// 循环遍历对象的下一个节点
let currNode = null
while((currNode = t.nextNode()) !== null) {
// 节点不为空,就一直循环遍历下去;直到为 null,才中断循环
console.log(currNode)
}
}
getChildren(document.body)
博客地址:https://ainyi.com/89
DOM 元素的循环遍历的更多相关文章
- json原理和jquey循环遍历获取所有页面元素
1.json原理: javascript object notation (javascript 对象表示法) 是一种轻量级的数据交换语言,由javascript衍生而出,适用于.NET java c ...
- DOM节点树和元素树--深度遍历
我们在阅读JS高级程序设计的时候,提到了节点树的概念.比如说: elem.parentNode---找elem的父节点: elem.childNodes---找elem的所有的直接子节点: elem. ...
- 【转】ArrayList循环遍历并删除元素的常见陷阱
转自:https://my.oschina.net/u/2249714/blog/612753?p=1 在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出b ...
- ArrayList循环遍历并删除元素的几种情况
如下代码,想要循环删除列表中的元素b,该怎么处理? public class ListDemo { public static void main(String[] args) { ArrayList ...
- ArrayList循环遍历并删除元素的常见陷阱
在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug.不妨把这个问题当做一道面试题目,我想一定能难道不少的人.今天就给大家说一下在ArrayList循环 ...
- 通过随机数获得学生成绩,并把每个元素赋值为学生的分数成绩,通过增强for循环遍历结果。
package com.Summer_0419.cn; /** * @author Summer * 通过随机数获得学生成绩,并把每个元素赋值为学生的分数成绩 */ public class Test ...
- Java中ArrayList循环遍历并删除元素的陷阱
ava中的ArrayList循环遍历并且删除元素时经常不小心掉坑里,昨天又碰到了,感觉有必要单独写篇文章记一下. 先写个测试代码: import java.util.ArrayList; public ...
- js之DOM元素遍历
对于元素间的空格,IE9之前的版本不会返回文本节点,而且他所有浏览器都会返回文本节点.这样就导致 使用childNodes和firstChild等属性时的行为不一致.从而有了Element Trave ...
- 利用forEach循环Dom元素…
大家都知道forEach是循环数组用的,而且很方便,可以丢掉for循环了,但是它不能循环Dom元素.其实我们可以利用call来完成forEach循环Dom; 假设有这样的HTML结构: <ul ...
随机推荐
- 学习Echarts:(二)异步加载更新
这部分比较简单,对图表的异步加载和更新,其实只是异步获取数据然后通过setOption传入数据和配置而已. $.get('data.json').done(function (data) { myCh ...
- JS函数和对象
1.函数 isNaN(数据)/parseInt/parseFloat/Number/prompt... 函数分为系统函数和自定义函数 function: 功能体,函数(方法),可以接受若干个数据,返回 ...
- [前端进阶课] 构建自己的 webpack 知识体系
webpack webpack 最出色的功能之一就是,除了 JavaScript,还可以通过 loader 引入任何其他类型的文件. Webpack 核心概念: Entry(入口):Webpack 执 ...
- MyBatis In的使用
http://blog.csdn.net/unei66/article/details/17792503 MyBatis In的使用 标签: mybatisin 2014-01-03 16:23 74 ...
- Vue刷新页面的三种方式
我们在写项目的时候,经常会遇到,用户执行完某个动作,改变了某些状态,需要重新刷新页面,以此来重新渲染页面 1.原始方法: location.reload(); 2.vue自带的路由跳转: this.$ ...
- zqt_helper 轻松开发Qt5 Widgets应用
目标: 1. 代码更加紧凑,所写即所到. 2. 代码层次更直观,直接反映界面窗口层次关系. 3. 不继承类,不重写虚函数,slot接收QEvent. 4. 简单写布局,忘掉api函数. 5. 免去一大 ...
- 实验6、Python-OpenCV宽度测量
一. 题目描述 测量所给图片的高度,即上下边缘间的距离. 思路: 将图片进行阈值操作得到二值化图片. 截取只包含上下边框的部分,以便于后续的轮廓提取 轮廓检测 得到结果 二. 实现过程 1.用于给图片 ...
- OPCUA+MQTT构建物联网通用框架
写在前面: 为了应对标准化和跨平台的趋势,更好的推广OPC,OPC基金会在OPCDA成功应用的基础上推出了一个新的OPC标准——OPC UA,OPCUA不再基于分布式组件对象模型(DCOM),而是以面 ...
- Swiper的jquery动态渲染不能滑动
<!-- 下面俩行代码就是解决异步加载数据导致swiper不轮播的关键 --> observer: true,//修改swiper自己或子元素时,自动初始化swiper observePa ...
- 第 7 篇:文章详情的 API 接口
作者:HelloGitHub-追梦人物 一旦我们使用了视图集,并实现了 HTTP 请求对应的 action 方法(对应规则的说明见 使用视图集简化代码),将其在路由器中注册后,django-restf ...