查找具有没有库或 getElementsByClassName 的类的元素

Find an element with a class without library or getElementsByClassName

本文关键字:元素 getElementsByClassName 有没有 查找      更新时间:2023-09-26

这是我被问到的问题,想知道该怎么做,或者这是否是一个技巧问题。我只用了一小段時間的JavaScript,所以我不太確定。

假设您有一个包含大量内容的网页。不使用任何库或getElementsByClassName,遍历DOM并找到具有特定类名的所有元素。

示例网页

<body>
    <div>
        <div class='myTarget'>
             Target exists here
        </div>
    </div>
    <div>
        <table>
            <tbody>
              <tr> <td class='myTarget'> Target exists here </td> </tr>
            </tbody>
        </table>
    </div>
    <div>
       <span class='myTarget notSameAsTarget'>Stuff<span>
    </div>
</body>

我的第一个想法是,这应该是一个递归函数,应该从根document.documentElement开始

.JS:

var root = document.documentElement;
var targetClass = 'myTarget';
var elementsWithTargetClass = []; // store in array
function traverse(element, targetClassName){
    // get class of current element
    var currentClass = element.className;
    // add to array if class matches
    if(currentClass.trim() === targetClassName)
        elementsWithTargetClass.push(element);
    // recursive call
    if(element.children){
         traverse(element, targetClassName);
    }
}

关于我缺少什么的任何建议?

    // recursive call - updated
    if(element.children){
         for(var child in element.children)
             traverse(element.children[child], targetClassName);
    }

您对 traverse() 的递归调用传递了最初传入的相同元素,因此它只是一遍又一遍地做完全相同的事情,直到堆栈溢出(嘿!您需要为元素的每个子级调用遍历,而不是将元素传递回去。

使用 document.querySelector .这不是getElementsByClassName(),也不是图书馆。;)

document.querySelector('.myTarget')

考虑具有多个类的元素,并以body开头:

  var targetClass = 'myTarget';
  var elementsWithTargetClass = []; // store in array
  var re = new RegExp("''b" + targetClass + "''b");
  
  traverse(document.body);
  
  for ( var j = 0; j < elementsWithTargetClass.length; ++j )
    elementsWithTargetClass[j].style.fontWeight = "bold";
  
  function traverse(element, targetClassName){
      // get class of current element
      var currentClass = element.className;
  
      if (currentClass.match(re))
      // add to array if class matches
    //  if(currentClass.trim() === targetClassName)
          elementsWithTargetClass.push(element);
  
      // recursive call
      if(element.children){
        for ( var i = 0; i < element.children.length; ++i )
           traverse(element.children[i]);
      }
  }
<div>
  <ul>
    <li class="myTarget">this</li>
    <li class="myTarget andAnotherClass">also this</li>
    <li>not this</li>
  </ul>
</div>

您正在进入许多递归,这使得调用堆栈增长到高。尝试将递归函数追逐到循环中。这应该不会给您带来任何问题。

var root = document.documentElement;
var targetClass = 'myTarget';
var elementsWithTargetClass = []; // store in array
pre_order(root);
function pre_order(node) {
  if(node.className == targetClass) 
    elementsWithTargetClass.push(node);       
  for(var i=0; i < node.childNodes.length; i++)
    pre_order(node.childNodes[i]);
}
console.log(elementsWithTargetClass);

JSFiddle