DOM树遍历之JS实现DFS&BFS

我们一般可以采用DFS(深度优先遍历)BFS(广度优先遍历)来遍历DOM树

介绍 DFS & BFS

我们来结合具体例子进行分析,给出HTML代码片段如下:

<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>

DFS总是先进入下一级节点,只有当下一级没有未遍历的子节点时才会进入到当前层级的其它节点。对于上面例子DFS遍历结果应为:

root, container, sidebar, menu, main, post, copyright

BFS则总是先遍历当前层级的所有节点,只有当当前层级所有节点都遍历结束后才会进入下一层级。对于上面例子BFS遍历结果应为:

root, container, sidebar, main, menu, post, copyright

DFS的具体实现

DFS主要采用递归实现,依次遍历节点,如果遍历到的节点有子节点,则开始遍历子节点

const DFSTraverse = (rootNodes, rootLayer) => {
      const roots = Array.from(rootNodes)
      while (roots.length) {
        const root = roots.shift()
        printInfo(root, rootLayer)
        // 如果有子节点,直接遍历子节点,同时将层级加1
        if (root.children.length) {
          DFSTraverse(root.children, rootLayer + 1)
        }
      }
    }

BFS的具体实现

BFS采用队列的思想,采用出队的方式遍历节点,如果遍历到的节点有子节点,则将子节点入队(这里处理节点层级的方式比DFS更复杂一些,因为这里将所有节点都放到了同一个数组中进行处理)

const BFSTraverse = (rootNodes, rootLayer) => {
      const roots = Array.from(rootNodes)
      const rootsLayer = [] // 单用一个数组存放每个节点的的层级
      // 初始化
      for (let i = 0; i < roots.length; i++) {
        rootsLayer.push(rootLayer)
      }
      var rootIdx = 0 // 记录当前处理roots中的第几个节点,方便查找rootsLayer中对应的层级
      while (roots.length) {
        const root = roots.shift() // 出队
        printInfo(root, rootsLayer[rootIdx])
        // 如果有子节点,将子节点放到roots队列中
        if (root.children.length) {
          Array.prototype.push.apply(roots, Array.from(root.children))
          // 将当前层级加1得到子节点的层级
          rootLayer = rootsLayer[rootIdx] + 1
          for (let i = 0; i < root.children.length; i++) {
            rootsLayer.push(rootLayer)
          }
        }
        // 处理下一个root节点
        rootIdx++
      }
    }
    

结果

先给大家补全代码:

// 输入节点信息
const printInfo = (node, layer) => {
      var str = ''
      for (let i = 1; i < layer; i++) {
        str += ' '
      }
      console.log(`${layer}:${str}${node.tagName} .${node.className}`);
    }

console.log('DFS *******************************');
DFSTraverse(document.querySelectorAll('.root'), 1);
console.log('BFS *******************************');
BFSTraverse(document.querySelectorAll('.root'), 1);

上面例子的运行结果为:
运行结果

参考

破解前端面试(80% 应聘者不及格系列):从 DOM 说起
Javascript-ONLY DOM Tree Traversal - DFS and BFS?

猜你喜欢

转载自www.cnblogs.com/homehtml/p/12512395.html