深度优先和广度优先遍历一棵DOM树

231 阅读1分钟
<!DOCTYPE html>
<html lang='en'>
<head>
  <meta charset='UTF-8' />
  <meta
    name='viewport'
    content='width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'
  />
  <meta http-equiv='X-UA-Compatible' content='ie=edge' />
  <title>Document</title>
</head>
<body>
<p>template</p>
<div id='box'>
  <p>hello <b>world</b></p>
  <img src='' alt='' />
  <!--注释-->
  <ul>
    <li>a</li>
    <li>b</li>
  </ul>
</div>

<script>
  /**
   * 访问一个节点,打印信息
   * @param n
   */
  function visitNode(n) {
    if (n instanceof Comment) {
      console.log('Comment node ---', n.textContent)
    }
    if (n instanceof Text) {
      if (n.textContent?.trim() !== '') {
        console.log('Text node ---', n.textContent)
      }
    }
    if (n instanceof HTMLElement) {
      console.log('Element node ---', `<${n.tagName.toLocaleLowerCase()}>`)
    }
  }

  /**
   * 深度优先遍历(递归实现)
   * @param root dom node
   */
  function depthFirstTraverse(root) {
    visitNode(root)
    if (root.childNodes.length) {
      Array.from(root.childNodes).forEach(item => {
        depthFirstTraverse(item)
      })
    }
  }

  /**
   * 深度优先遍历(栈实现)
   * @param root dom node
   */
  function depthFirstTraverseByStack(root) {
    const stack = []
    stack.push(root)
    while (stack.length > 0) {
      const node = stack.pop()
      visitNode(node)
      if (node.childNodes.length) {
        Array.from(node.childNodes)
          .reverse()
          .forEach(item => {
            stack.push(item)
          })
      }
    }
  }

  /**
   * 广度优先遍历(队列实现)
   * @param root dom node
   */
  function breadthFirstTraverse(root) {
    const queue = []
    queue.push(root)
    while (queue.length > 0) {
      const node = queue.shift()
      visitNode(node)
      if (node.childNodes.length) {
        Array.from(node.childNodes).forEach(item => {
          queue.push(item)
        })
      }
    }
  }
</script>
</body>
</html>