使用递归重新实现getElementsByClassName - Javascript

3

我目前正在学习递归,并尝试通过递归遍历DOM来重新实现getElementsByClassName函数。我终于感觉理解了这些概念,但是当我将匹配元素推入结果数组时却出现了问题。以下是我的代码:

var getElementsByClassName = function(className){
  var results = [];
  var domWalker = function(node) {
    for (var i=0; i<node.children.length; i++) {
        if (node.children[i].classList.contains(className)) {
            console.log(node.children[i])
            results.push(node.children[i])
        }

        if (node.children[i].children.length > 0) {
            domWalker(node.children[i])
        }

    }
    return results;
  };
  domWalker(document.body);
  console.log(results)
};

基本上,我需要结果数组以HTML格式保留它在HTML中找到的匹配元素,如下所示:[<div class="title"></div>, <button class="click"></button>],但是当我将这些元素推入我的结果数组时,它们会变成 div.title,button.click 格式。我在调用results.push之前添加了console.log语句来查看结果是否以正确格式出现,结果都是正确的。推送到数组中的结果就是我要找的结果,只不过显示为错误的格式。为什么push会导致结果格式改变,我该如何解决这个问题?

2
只需更改控制台格式化数组以使更多元素在屏幕上更加美观,而数组项本身就是您想要的内容。如果您需要HTML源代码,则最接近的方法是将node.children[i].outerHTML推入您的数组中,而不是元素对象。 - dandavis
2个回答

1

我曾经解决过这个问题。虽然我没有仔细阅读你的解决方案,但这是我的解决方案,有大量的注释。希望它有所帮助:

var getElementsByClassName = function(className, node){
  // The empty results array, which gets created whenever the function is
  // called. 
  var results = [];

  // Default the node to the document's body if it isn't set. This way, we can
  // call the function recursively with child elements, but never have to
  // worry about it the first time around.
  node = node || document.body;

  // If the node contains the class list in question, let's push it into the
  // results array.
  if (node.classList && node.classList.contains(className)) {
    results.push(node);
  }

  // Now, let's fetch the child nodes of the current node.
  var children = node.childNodes;

  // If child nodes exist, then we proceed here.
  if (children) {
    // Let's now loop over all child nodes of the current node in question. This
    // way, we'll be able to perform checks on each child node.
    for (var i = 0; i < children.length; i++) {
      // Fetch the i child node.
      var child = children[i];

      // At this point, we want to pass the child node back into the function,
      // implementing recursion. The same checks above will occur, and if the
      // node has the class name, it will be added to the results array from
      // that function call.
      //
      // This returns an array, and we need to merge it with the current set
      // of results, so we concat it.
      //
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
      results = results.concat(getElementsByClassName(className, child));
    }
  }

  // We then return the combined results array from all the recursive function
  // calls!
  return results;
};

0

node.children[i] 保存了 HTML 元素的引用。

console.log() 应用了隐式的 .toString() 方法,输出你所看到的内容。

你需要添加以下额外的代码(扩展到你发现的所有可能的标签名称):

var el = node.children[i];
el = '<' + el.tagName + (el.className ? ' class="' + el.className + '"': '') + '/>';
console.log(el);
results.push(el);

为什么不直接使用 el.outerHTML - dandavis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接