广度优先遍历,即父层遍历结束,才开始遍历子层,然后一直往下遍历,如果是下面这样一颗DOM树
<div class="root">
<div class="container">
<section class="sidebar">
<ul class="menu"></ul>
</section>
<section class="main">
<article class="post"></article>
<p class="copyright"></p>
</section>
</div>
</div>
则需要遍历为
DIV .root
DIV .container
SECTION .sidebar
SECTION .main
UL .menu
ARTICLE .post
P .copyright
这种形式,平级的子元素显示在一起,并且最好隔开,这样更容易理解。下面就开始写BFS的实现方法。
首先需要一个打印函数,便于打印信息
let printInfo = (node) => {
console.log(node.tagName, '.' + node.className)
然后是遍历函数,遍历中需要一个中间数组,即父层遍历时每遍历一个元素即将此元素的子元素写入中间数组,遍历完之后,如果此数组长度不为0,则接着遍历下一层,直至最后一层。
// root为你需要遍历的根节点,此处为.root
let root = document.getElementsByClassName('root')[0]
// 此时遍历的为current,记录下一层遍历的为nextRound,初始值为root
let current = []
let nextRound = [root]
// 遍历函数
function bfs () {
current = nextRound
// 将nextRound重置,切记不可直接设置length为0,这样current也会重置
nextRound = []
Array.from(current).forEach(function (el) {
printInfo(el)
Array.from(el.children).forEach(function (element) {
nextRound.push(element)
})
})
}
// 开始遍历
while(nextRound.length){
bfs()
}
深度优先遍历以深度为主,即遍历完某一个节点之后,才会继续往下遍历兄弟节点,这个只需要循环遍历就行了。
function dfs (node) {
printInfo(node)
if(node.children.length){
Array.from(node.children).forEach(function (el) {
dfs(el)
})
}
}
dfs(root)
这样打印出来的就是
DIV .root
DIV .container
SECTION .sidebar
UL .menu
SECTION .main
ARTICLE .post
P .copyright
还有一点就是childNodes和children这两个时不太一样的,childNodes会将文本节点也打印出来,这时候你就会看到很多undefined .undefined
这样的东西,所以尽量使用children,然后用Array.from将其从HTMLCollection变为一个真正的数组。
本文参考: https://juejin.im/post/58f558efac502e006c3e5c97,王仕军的掘金专栏