欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DOM中BFS(广度优先遍历)和DFS(深度优先遍历)的方法

程序员文章站 2022-05-22 20:58:27
...

广度优先遍历,即父层遍历结束,才开始遍历子层,然后一直往下遍历,如果是下面这样一颗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,王仕军的掘金专栏