获取相对于父元素的子元素索引


160

假设我有这个标记:

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

我有这个jQuery:

$("#wizard li").click(function () {
    // alert index of li relative to ul parent
});

li单击该子项时,如何获得子项相对于其父项的索引li

例如,当您单击“步骤1”时,alert应弹出带有“ 0”的。

Answers:


247
$("#wizard li").click(function () {
    console.log( $(this).index() );
});

但是,与其为每个列表项附加一个单击处理程序,不如使用delegate一个更好的(性能方面),它看起来像这样:

$("#wizard").delegate('li', 'click', function () {
    console.log( $(this).index() );
});

在jQuery 1.7+中,您应该使用on。下面的示例将事件绑定到#wizard元素,就像委托事件一样工作:

$("#wizard").on("click", "li", function() {
    console.log( $(this).index() );
});

3
嗨,redsquare ..我正在用jQuery进行练习,我对委托:D .n00b有点。为什么委托比直接在元素上附加事件好?
stecb 2011年

1
@steweb-嘿-因为一个事件处理程序比潜在的事件处理程序好得多。如果列表很大,将事件附加到dom上可能会很昂贵,因此通常我会尽可能使用上述规则,而不是在每个元素上使用单独的处理程序。一篇更深入的文章是briancrescimanno.com/2008/05/19/…-也是Google“ javascript事件委托”
redsquare 2011年

好的,因此,以这种方式管理事件比经典的“ dom附件”要轻:) ..谢谢!
stecb 2011年

@steweb-它也更轻巧,因为jquery不需要对所有li元素进行初始查找。它只是查找容器并在该级别进行侦听,以查看所单击的对象是否为li。
redsquare 2011年

这个.index方法对我很有帮助。我正在使用jQuery Sortable进行排序,但是它将语义排名信息存储在DOM中。使用.index(),我可以将排名真正撤出dom。谢谢!
SimplGy 2013年

41

就像是:

$("ul#wizard li").click(function () {
  var index = $("ul#wizard li").index(this);
  alert("index is: " + index)
});

9
很棒的补充-我们可以找到相对于父选择器的索引。+1
BasTaller 2012年

1
首选此答案,因为它实际上回答了问题,而不是示例的可能解决方案
DarkMukke,2015年

8

看一下这个例子

$("#wizard li").click(function () {
    alert($(this).index()); // alert index of li relative to ul parent
});

4

如果您不想这样做,则无需像jQuery这样的大型库即可完成此操作。要通过内置的DOM操作实现此目的,请获取li数组中兄弟姐妹的集合,然后单击以检查该indexOf数组中被单击的元素。

const lis = [...document.querySelectorAll('#wizard > li')];
lis.forEach((li) => {
  li.addEventListener('click', () => {
    const index = lis.indexOf(li);
    console.log(index);
  });
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

或者,通过事件委托:

const lis = [...document.querySelectorAll('#wizard li')];
document.querySelector('#wizard').addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li> which is a child of wizard:
  if (!target.matches('#wizard > li')) return;
  
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

或者,如果子元素可能会动态更改(例如待办事项列表),那么您必须li在每次单击时构造s 数组,而不是事先构造:

const wizard = document.querySelector('#wizard');
wizard.addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li>
  if (!target.matches('li')) return;
  
  const lis = [...wizard.children];
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>


$(...)。indexOf不是函数
Kareem

2
我的答案中没有任何代码片段会产生该错误-您可以按“运行代码片段”以查看它们是否正常运行。如果遇到该错误,则说明您使用的是不同的代码-听起来像是在使用jQuery,但是我的回答是显示如何在不使用 jQuery 的情况下完成此类操作
SomePerformance

很公平。是的,我正在使用JQuery。谢谢
Kareem

3

Delegate和Live易于使用,但是如果您不再动态添加任何li:s,则也可以将事件延迟与常规绑定/单击一起使用。使用此方法应该可以提高性能,因为不必为新的匹配元素而监视DOM。还没有任何实际数字,但这很有意义:)

$("#wizard").click(function (e) {
    var source = $(e.target);
    if(source.is("li")){
        // alert index of li relative to ul parent
        alert(source.index());
    }
});

您可以在jsFiddle上对其进行测试:http : //jsfiddle.net/jimmysv/4Sfdh/1/


1
当您说此“不必监视DOM”时,您指的是什么?jq委托不监视dom。
redsquare 2011年

@redsquare给我的印象是Delegate只是Live的一种更有效的变体。这来自api.jquery.com/delegate:“根据特定的一组根元素,为现在或将来与选择器匹配的所有元素,向一个或多个事件附加处理程序。” 将来必须监视绑定吗?
jimmystormig 2011年

不,它只是像上面的代码一样在容器上使用委派。如果将新的li元素插入容器,则将触发容器click事件,并且一切仍然有效。无需监控。
redsquare 2011年

@redsquare是的,您是正确的。即使在DOM加载后添加了新元素,我的解决方案仍然有效。由于Delegate在内部使用Live(请参阅stackoverflow.com/questions/2954932/…),因此感觉仍然是更优化但不太方便。但正如我所说,我没有数字。
jimmystormig 2011年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.