如何从前一个元素的 NodeList 中获取所有类名?

Posted

技术标签:

【中文标题】如何从前一个元素的 NodeList 中获取所有类名?【英文标题】:How to get all classname from previous element's NodeList? 【发布时间】:2019-10-12 17:33:40 【问题描述】:

我想为放置在某个元素块之后的每个按钮添加一些事件侦听器。如果单击,此按钮旨在返回上一个元素块中的所有元素类。

我在这里找到了从 NodeList 获取类的脚本,https://gist.github.com/cssence/41c8279810b1db71670d.js

for (var k = 0; k < trigger.length; k++) 
  trigger[k].addEventListener('click', function(e) 
    nav.classList.toggle('hidden');
    (function listAllUsedClassNames() 
      var classNames = ;
      Array.prototype.forEach.call(this.previousElementSibling.querySelectorAll("*"), function(element) 
        if (typeof element.className === "string") 
          element.className.split(" ").forEach(function(className) 
            if (className) 
              classNames[className] = true;
            
          );
        ;
      );
      return Object.keys(classNames);
    ());
  , false);

我想要一些数组包含单击按钮后返回的前一个块的所有类。如果结果是唯一的并且没有任何重复项会更好。

【问题讨论】:

你也想要前一个元素的嵌套元素类吗? 是否有任何解决方案,所以结果是唯一的,而不是重复的。我想在这里使用数组来获取一些元素样式。 您应该在发布问题时详细说明要求。 是的,我想要前一个元素的嵌套元素类。与 DOM 树一样深。但没有重复值。 【参考方案1】:

要获取上一个元素,请使用previousElementSibling。遍历childNodes 以获取使用classList 的元素类。

let classes = [];
document.querySelectorAll('button')
  .forEach(button => 
    button.addEventListener('click', function() 
      classes = [];
      const prev = this.previousElementSibling;
      classes.push(...prev.classList);
      prev.childNodes.forEach(child => 
        if(child.nodeType == 3) return; // Ignore text node
        classes.push(...child.classList);
      )
      console.log(classes);
    );
  );
<div class="first">
  <p class="childOfFirst">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Repudiandae totam dicta libero vero dolore aperiam consectetur. Non veritatis quo praesentium!</p>
</div>
<button>Button1</button>
<div class="second">
  <p class="childOfSecond">Lorem ipsum dolor sit amet consectetur adipisicing elit. Aspernatur, hic.</p>
</div>
<button>Button2</button>

对于多重嵌套,使用recursion

let classes = [];

document.querySelectorAll('button')
    .forEach(button => 
        button.addEventListener('click', function() 
            classes = [];
            const prev = this.previousElementSibling;
            if(prev.children.length > 0) 
                const output = getNestedClasses([...prev.children]);
                classes.push(...prev.classList, ...output);
                console.log('With Duplicates', classes);
                const uniqueClassList = removeDuplicateClasses(classes)
                console.log('Without Duplicates', uniqueClassList);
            
        );
    );

function getNestedClasses(childrens) 
    return childrens.reduce((accu, ele) => 
        if(ele.children.length > 0) 
            accu.push(...ele.classList);
            return accu.concat(getNestedClasses([...ele.children]));
         else 
            return accu.concat([...ele.classList]);
        
    , []);


function removeDuplicateClasses(classArr) 
    return Object.keys(classArr.reduce((accu, name) => 
        accu[name] += (accu[name] || 0);
        return accu;
    , ));
<div class="first">
    <p class="firstChild">First Child
        <span class="firstGrandChild">First Grand Child</span>
        <span class="secondGrandChild">Second Grand Child</span>
    </p>    
    <p class="secondChild duplicate">Second Child</p>
    <p class="duplicate"></p>
    <p class="thirdChild">Third Child</p>
</div>
<button>Button1</button>

【讨论】:

嗨,@randomSoul,在我在深度 DOM 树中测试它们之后,因为每个父母都有三四个孩子,每个孩子都有自己的孩子。出现错误:Uncaught TypeError: classes.push is not iterable (cannot read property Symbol(Symbol.iterator)) @ian - 如果有多个嵌套,第一个代码 sn-p 用于一级嵌套,请使用递归。我还添加了用于多个嵌套的代码以删除重复的类。见编辑。

以上是关于如何从前一个元素的 NodeList 中获取所有类名?的主要内容,如果未能解决你的问题,请参考以下文章

js怎么获取元素的class名

使用 NodeList 遍历 XML 中的所有元素

在javascript将NodeList作为Array数组处理的方法

递归实现查找页面所有节点

JavaScript 学习-28.元素与节点(HTMLCollection 和 NodeList)

如何通过 url 从网站获取所有网站图标