简体   繁体   English

Vanilla JS:如何获取某个类的父元素的索引?

[英]Vanilla JS: How to get index of parent element with a certain class?

In a nutshell :简而言之

On click of a link below in the given HTML, I need to get the index of the parent with class "analytics".在给定 HTML 中单击下面的链接时,我需要使用“analytics”类获取父项的索引。 For example, clicking the link "myID2 Link 1" would return 1.例如,单击链接“myID2 Link 1”将返回 1。

<ul id="myID1" class="analytics" data-attribute="hpg:shocking">
  <li><a href="http://myurl.com/">myID1 Link 1</a></li>
  <li><a href="http://myurl.com/">myID1 Link 2</a></li>
  <li><a href="http://myurl.com/">myID1 Link 3</a></li>
</ul>
<ul id="myID2" class="analytics" data-attribute="hpg:expected">
  <li><a href="http://myurl.com/">myID2 Link 1</a></li>
  <li><a href="http://myurl.com/">myID2 Link 2</a></li>
  <li><a href="http://myurl.com/">myID2 Link 3</a></li>
</ul>
<ul id="myID3" class="analytics" data-attribute="hpg:unexpected">
  <li><a href="http://myurl.com/">myID3 Link 1</a></li>
  <li><a href="http://myurl.com/">myID3 Link 2</a></li>
  <li><a href="http://myurl.com/">myID3 Link 3</a></li>
</ul>

What I've tried :我试过的

I'm currently using two separate loops, one for iterating through the parents, the other for adding a click event to the links.我目前使用两个单独的循环,一个用于遍历父级,另一个用于向链接添加点击事件。

// helper function to check parent for a class
function hasParentWithClass(element, classname) {
  if (element.className.split(' ').indexOf(classname) >= 0) {
    return true;
  }
  return element.parentNode && hasParentWithClass(element.parentNode, classname);
}

// get all elements with class "analytics"
var analytics = document.querySelectorAll('.analytics');
var containerClass = [];

for (var z = 0; z < analytics.length; z++) {
  var inc = z + 1;
  containerClass.push(analytics[z].getAttribute('id'));
}

var links = analytics.getElementsByTagName('a');

for (var i = 0; i < links.length; i++) {
  links[i].addEventListener('click', function(e) {
    e.preventDefault();

    if (hasParentWithClass(this, 'analytics')) {
    // output index of parent
    } else {
    // do nothing
    }
  }, false);
}

The problem :问题

I'm struggling with using the logic from the first loop inside the second loop.我正在努力使用第二个循环中第一个循环的逻辑。 Specifically, searching var containerClass from within the second for loop to get the index of the parent, as it's stored in var containerClass.具体来说,从第二个 for 循环中搜索 var containerClass 以获取父级的索引,因为它存储在 var containerClass 中。 .indexOf did not serve me well. .indexOf 没有很好地为我服务。

What is the most straightforward, efficient way to accomplish this?实现这一目标的最直接、最有效的方法是什么?

This is much simpler than you think.这比你想象的要简单得多。 If we assign a click event handler to the parent elements we can use event bubbling to solve the issue.如果我们为父元素分配一个点击事件处理程序,我们可以使用事件冒泡来解决这个问题。 When you click a link, it will not only trigger the click event for the link you clicked, but that event will "bubble" up through the ancestor elements of that link as well.当您单击一个链接时,它不仅会触发您单击的链接的click事件,而且该事件还会通过该链接的祖先元素“冒泡”。 If we capture the event at the parent, we can just get its index.如果我们在父级捕获事件,我们就可以得到它的索引。

Also, as @Dave Thomas points out, your HTML structure for your list(s) is not valid.此外,正如@Dave Thomas 指出的那样,您的列表的 HTML 结构无效。

 // Get all the .analytics elements var analytics = document.querySelectorAll(".analytics"); // Loop through them Array.prototype.slice.call(analytics).forEach(function(item, index, arry){ // Set up click event handlers for each of the parents item.addEventListener("click", function(evt){ // Just access the index of the parent within the group console.clear(); console.log("The index of the parent is: " + index) // Now, display the index of the link within its parent .analytics element // Get all the anchors in the current analytics container var anchors = Array.prototype.slice.call(item.querySelectorAll("a")); // Get the index of the anchor within the set of anchors var idx = Array.prototype.indexOf.call(anchors, evt.target); console.log("The index of the link within the parent is: " + idx); }); });
 <div id="myID1" class="analytics" data-attribute="hpg:shocking"> <ul> <li><a href="#">myID1 Link 1</a></li> <li><a href="#">myID1 Link 2</a></li> <li><a href="#">myID1 Link 3</a></li> </ul> </div> <div id="myID2" class="analytics" data-attribute="hpg:expected"> <ul> <li><a href="#">myID2 Link 1</a></li> <li><a href="#">myID2 Link 2</a></li> <li><a href="#">myID2 Link 3</a></li> </ul> </div> <div id="myID3" class="analytics" data-attribute="hpg:unexpected"> <ul> <li><a href="#">myID3 Link 1</a></li> <li><a href="#">myID3 Link 2</a></li> <li><a href="#">myID3 Link 3</a></li> </ul> </div>

Here is another way:这是另一种方式:

document.querySelectorAll('li').forEach((item) => {
    item.addEventListener('click', (e) => {
        const index = Array.from(item.parentNode.children).indexOf((item))
        console.log(index);
    })
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM