【问题标题】:I need help using recursion to navigate every element in the DOM我需要帮助使用递归来导航 DOM 中的每个元素
【发布时间】:2020-05-25 07:23:18
【问题描述】:

我需要使用递归来导航 DOM 中的每个元素,并且对于每个 body 元素,确定它是否是一个元素节点。如果是,我需要向它添加一个子节点。我需要使用 JavaScript 来完成这项任务。以下是我的 JavaScript 文件中的内容:

    window.addEventListener("load", function() {

      var highlightButton = document.getElementById("highlight");
      highlightButton.addEventListener('click', search);

      function search(node) {
       if (node.nodeType === 1) {
       var spanEl = document.createElement("span");
       spanEl.className = "hoverNode";
       node.appendChild(spanEl);
       spanEl.innerHTML = spanEl.parentNode.tagName;
     }
   }
 })

我了解如何追加子节点,但不知道如何遍历整个 DOM 并将子节点追加到每个元素。

【问题讨论】:

  • 一个文档只能有一个 HTML 元素,body elements 只能是 HTML 元素的子元素。根据定义,主体元素是元素节点。所以你不需要递归来做到这一点。如果您只想查看文档中的每个元素,那就另当别论了。除非“每个正文元素”实际上是指“正文中的每个元素”?
  • 这是一个需要使用递归的学校作业。它特别要求我们导航 DOM 中的每个元素,并且对于 body 中的每个元素,确定它是否是元素节点(nodeType == 1)元素,然后向其添加子节点。

标签: javascript recursion dom


【解决方案1】:

除了支持旧版浏览器(如 IE6 和 7)之外,是否有任何特定原因暗示要创建递归函数

如果没有,您可以简单地使用document.body.querySelectorAll('*') 选择 DOM 中的每个元素节点,而忽略 body 元素之外的节点。一个例子是:

window.addEventListener('load', function () {
    var highlightButton = document.getElementById("highlight");

    function search () {
        document.body.querySelectorAll('*').forEach(function (el) { 
            var spanEl = document.createElement('span');

            spanEl.innerHTML = el.tagName; 
            spanEl.className = 'hoverNode';
            el.appendChild(spanEl); 
        });
    }

    highlightButton.addEventListener('click', search);
});

如果是,那么一个选项是:

window.addEventListener('load', function () {
    var highlightButton = document.getElementById("highlight");

    // traverse downwards from rootEl while excluding Comment elements on IE6 7 & 8
    function traverseDOMFrom (rootEl, iterator) {
        if (!rootEl || rootEl.nodeType !== 1 || typeof iterator !== 'function') {
            return;
        }

        if (rootEl.children && rootEl.children.length > 0) {
            Array.prototype.slice.call(rootEl.children).forEach(function (el) {
                traverseDOMFrom(el, iterator);
            });
        }

        iterator(rootEl);
    }

    function search () {
        traverseDOMFrom(document.body, function (el) { 
            var spanEl = document.createElement('span');

            spanEl.innerHTML = el.tagName;
            spanEl.className = 'hoverNode';
            el.appendChild(spanEl); 
        });
    }

    highlightButton.addEventListener('click', search);
});

请注意,在这两种情况下,如果您想在 IE6、7 和 8 上支持这些功能,则需要为 Array.prototype.forEach()EventTarget.addEventListener() 使用 polyfill! 否则,您也可以实现通过使用自定义 for loop 迭代元素的数组来得到相同的结果,对于这个 .addEventListener,如果不需要支持多个侦听器,可以使用简单的 .onload 事件处理程序。

【讨论】:

    【解决方案2】:

    鉴于“每个主体元素”实际上意味着“主体中的每个元素”,您可以从一个元素开始并获取其所有子元素。循环遍历子元素,如果有任何类型为 1 且具有子节点,则使用该元素再次调用该函数。

    如果它没有子节点,则转到下一个子节点,等等。以下只是递归所有节点并仅挑选类型 1 的示例。你可以修改它来做任何事情。

    // Call with a document or HTML element
    function checkBodyElements(node) {
    
      // Recursive function
      function traverseBody(node) {
    
        if (node.childNodes.length) {
    
          // Loop over every child node
          node.childNodes.forEach(child => {
    
            // If it's a type 1, call the function recursively
            if (child.nodeType == 1) {
              console.log(child.tagName, child.nodeType)
              traverseBody(child);
            }
          });
        }
      }
    
      // Get the body element      
      let body = node.querySelector('body');
      
      // If a body element was found, traverse its children
      if (body) {
        traverseBody(body);
      }
    }
    
    window.onload = checkBodyElements(document);
    <div>
      <div>
        <p><span></span>
        </p>
      </div>
      <div>
        <p><span></span>
        </p>
      </div>
    
    </div>

    【讨论】:

      猜你喜欢
      • 2021-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      相关资源
      最近更新 更多