​博客地址:https://ainyi.com/89

获取 DOM 元素的几种方式

get 方式:

  1. getElementById
  2. getElementsByTagName
  3. getElementsByClassName
  4. getElementsByName

返回类型 HTMLCollection[]


query 方式:

  1. querySelector
  2. 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 元素的循环遍历的更多相关文章

  1. json原理和jquey循环遍历获取所有页面元素

    1.json原理: javascript object notation (javascript 对象表示法) 是一种轻量级的数据交换语言,由javascript衍生而出,适用于.NET java c ...

  2. DOM节点树和元素树--深度遍历

    我们在阅读JS高级程序设计的时候,提到了节点树的概念.比如说: elem.parentNode---找elem的父节点: elem.childNodes---找elem的所有的直接子节点: elem. ...

  3. 【转】ArrayList循环遍历并删除元素的常见陷阱

    转自:https://my.oschina.net/u/2249714/blog/612753?p=1 在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出b ...

  4. ArrayList循环遍历并删除元素的几种情况

    如下代码,想要循环删除列表中的元素b,该怎么处理? public class ListDemo { public static void main(String[] args) { ArrayList ...

  5. ArrayList循环遍历并删除元素的常见陷阱

    在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug.不妨把这个问题当做一道面试题目,我想一定能难道不少的人.今天就给大家说一下在ArrayList循环 ...

  6. 通过随机数获得学生成绩,并把每个元素赋值为学生的分数成绩,通过增强for循环遍历结果。

    package com.Summer_0419.cn; /** * @author Summer * 通过随机数获得学生成绩,并把每个元素赋值为学生的分数成绩 */ public class Test ...

  7. Java中ArrayList循环遍历并删除元素的陷阱

    ava中的ArrayList循环遍历并且删除元素时经常不小心掉坑里,昨天又碰到了,感觉有必要单独写篇文章记一下. 先写个测试代码: import java.util.ArrayList; public ...

  8. js之DOM元素遍历

    对于元素间的空格,IE9之前的版本不会返回文本节点,而且他所有浏览器都会返回文本节点.这样就导致 使用childNodes和firstChild等属性时的行为不一致.从而有了Element Trave ...

  9. 利用forEach循环Dom元素…

    大家都知道forEach是循环数组用的,而且很方便,可以丢掉for循环了,但是它不能循环Dom元素.其实我们可以利用call来完成forEach循环Dom; 假设有这样的HTML结构: <ul ...

随机推荐

  1. 「雕爷学编程」Arduino动手做(8)——湿度传感器模块

    37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...

  2. Django之Middleware中间件方法使用

    自定义中间件五个方法(部分方法)实例 自定义中间件项目: 模板Templates login.html {% load static %} <!DOCTYPE html> <html ...

  3. python3.x 基础七:面向对象进阶

    类的高级方法: 1.静态方法:在类方法前增加关键字@staticmethod,将普通方法变成静态方法,不能再次传值,不能访问实例变量或者类变量,与类的关系仅仅是通过类名进行调用 2.类方法:在类方法前 ...

  4. 理解javascript中的连续赋值

    之前在扒源码时经常看到类似的连续赋值操作:  var a = b = 1;  在某度搜了众多前辈的博客,总算对这骚操作有点眉目. Case analysis 首先,javascript中连续赋值最典型 ...

  5. 前端内网穿透,localtunnel你值得拥有!

    一个前端在调试本地页面时,总会有些稀奇古怪的需求,比如产品立刻要看你的页面效果,而此时有没有上线环境折腾给他看,那此时通过内网穿透的方式,实时把你的项目生成一个在线链接丢给他,让他去找那一像素的bug ...

  6. Verilog代码和FPGA硬件的映射关系(五)

    既然我们可以指定寄存器放在IOB内,那我们同样也可以指定PLL的位置.首先要确保我们有多个PLL才行.如图1所示,我们所使用的EP4CE10F17C8芯片刚好有两个. 图 1 为了演示这个例子,我们使 ...

  7. 《机器学习Python实现_09_02_决策树_CART》

    简介 CART树即分类回归树(classification and regression tree),顾名思义,它即能用作分类任务又能用作回归任务,它的应用比较广泛,通常会用作集成学习的基分类器,总得 ...

  8. Android_适配器(adapter)之SimpleAdapter

    概述 SimpleAdapter是一种 简单的适配器,将静态数据映射到布局xml对应的视图上.它也是BaseAdapter的子类. SimpleAdapter数据映射的组件有3类(从官网api或Sim ...

  9. CNN卷积神经网络的卷积层、池化层的输出维度计算公式

    卷积层Conv的输入:高为h.宽为w,卷积核的长宽均为kernel,填充为pad,步长为Stride(长宽可不同,分别计算即可),则卷积层的输出维度为: 其中上开下闭开中括号表示向下取整. MaxPo ...

  10. BZOJ1003 物流运输 题解

    发现\(n,m\)很小,我们可以先把任意\(2\)天的最短路都给求出来,考虑\(DP\),设\(f[i][j]\)表示\(j+1\)~ \(i\)这几天内走的是最短路线的最优方案,显然最优情况下\(j ...