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

IT技术 javascript jquery
2021-01-19 03:58:48

假设我有这个标记:

<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”的字样。

6个回答
$("#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() );
});
这个 .index 方法对我很有帮助。我使用 jQuery Sortable 进行排序,但它将语义排名信息存储在 DOM 中。使用 .index(),我可以非常干净地将排名从 dom 中拉回来。谢谢!
2021-03-14 03:58:48
@steweb - 它也更轻,因为 jquery 不需要对所有 li 元素进行初始查找。它只是查找容器并在该级别侦听以查看单击的对象是否为 li。
2021-03-18 03:58:48
嗨 redsquare .. 我正在用 jQuery 练习,我对委托有点不了解 :D .. 为什么委托比直接在元素上附加事件更好?
2021-03-28 03:58:48
@steweb - 嘿 - 因为一个事件处理程序比潜在的多个事件处理程序更可取。如果您有大列表,将事件附加到 dom 可能会很昂贵,因此作为规则,我尝试尽可能使用上述内容,而不是在每个元素上使用单独的处理程序。一篇更深入的文章是briancrescimanno.com/2008/05/19/... - 也是谷歌“javascript 事件委托”
2021-04-04 03:58:48
好的,所以,以这种方式管理事件比经典的“dom 附件”更轻松:) ..谢谢!
2021-04-10 03:58:48

就像是:

$("ul#wizard li").click(function () {
  var index = $("ul#wizard li").index(this);
  alert("index is: " + index)
});
很好的补充 - 我们可以找到相对于父选择器的索引。+1
2021-04-04 03:58:48
更喜欢这个答案,因为它实际上回答了问题,而不是示例的可能解决方案
2021-04-08 03:58:48

看看这个例子

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

如果您不想,则不需要像 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 不是函数
2021-03-15 03:58:48
很公平。是的,我正在使用 JQuery。谢谢
2021-03-26 03:58:48
我的答案中没有任何代码片段会产生该错误 - 您可以按“运行代码片段”来查看它们的工作情况。如果您收到该错误,则说明您使用的是不同的代码 - 听起来您正在使用 jQuery,但我的答案是展示如何在没有jQuery情况下完成此类事情
2021-04-08 03:58:48

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/

当您说“不需要监视 DOM”时,您指的是什么?jq 委托不监视 dom。
2021-03-12 03:58:48
@redsquare 我的印象是 Delegate 只是 Live 的一种更有效的变体。这是来自api.jquery.com/delegate:“根据一组特定的根元素,现在或将来,将处理程序附加到与选择器匹配的所有元素的一个或多个事件。” 以后绑定一定要监控吗?
2021-03-20 03:58:48
@redsquare 是的,你是对的。即使在 DOM 加载后添加了新元素,我的解决方案也能正常工作。由于 Delegate 在内部使用 Live(参见stackoverflow.com/questions/2954932/...),它仍然感觉这更优化但不太方便。但正如我所说,我没有数字。
2021-04-05 03:58:48
不,它只是像上面的代码一样在容器上使用委托。如果你在容器中插入一个新的 li 元素,容器的点击事件仍然会被触发并且一切仍然有效。无需监控。
2021-04-08 03:58:48