前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DOM 元素的循环遍历

DOM 元素的循环遍历

原创
作者头像
Krry
修改2020-06-10 17:09:50
6.4K0
修改2020-06-10 17:09:50
举报
文章被收录于专栏:Krryblog

博客地址: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

获取元素

首先用两种方式获取元素

代码语言:txt
复制
let a = document.getElementsByClassName('title')
let b = document.querySelectorAll('.title')

一般循环

get 方式

get 方式获取的 dom 元素,仅可使用==for-in、for-of、for==循环

代码语言:txt
复制
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 元素,类似 aindex

==ƒ namedItem() { native code }==

可通过 a.namedItem('popo') 获取 name 属性为 'popo' 的 dom 元素(若多个元素有相同的 name 属性,返回第一个)

for-of、for 循环可获取每个 dom 元素:

代码语言:txt
复制
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,循环得出的结果稍有不同

代码语言:txt
复制
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() 方法可将这些集合转换成普通数组,这样就可以享用数组的各种方法了

代码语言:txt
复制
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 中的所有直接子级的元素节点:

代码语言:txt
复制
<div id="list">
  <p>hello</p>
  <span>world</span>
  <em>cookieParse()</em>
</div>

用 firstChild,lastChild 进行元素遍历

代码语言:txt
复制
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

代码语言:txt
复制
let list = document.getElementById('list')

let child = list.firstElementChild

while(child) {
  console.log( child )
  child = child.nextElementSibling
}

深度优先遍历

遍历所有节点

深度优先遍历:当同时有兄弟节点和子节点的时候,总是优先遍历子节点

代码语言:txt
复制
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

显示文档类型节点

优化如下:

代码语言:txt
复制
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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 获取元素
  • 一般循环
    • get 方式
      • query 方式
      • ES6 转换普通数组
      • 深度遍历
        • 遍历直接子级元素
          • 深度优先遍历
            • 优化深度优先遍历
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档