【问题标题】:Get index of element as child relative to parent获取元素的索引作为子元素相对于父元素
【发布时间】:2011-06-27 03:06:58
【问题描述】:

假设我有这个标记:

<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 相对于其父级的索引?

例如,当您点击“Step 1”时,应该会弹出一个带有“0”的alert

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:
    $("#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() );
    });
    

    【讨论】:

    • 嗨 redsquare.. 我正在使用 jQuery 练习,我对委托有点不理解 :D .. 为什么委托比直接在元素上附加事件更好?
    • @steweb - 嘿 - 因为一个事件处理程序比可能的多个事件处理程序更可取。如果您有大型列表,则将事件附加到 dom 可能会很昂贵,因此作为一项规则,我尝试尽可能使用上述内容,而不是每个元素上的单独处理程序。一篇更深入的文章是 briancrescimanno.com/2008/05/19/… - 也是 google 'javascript event delegate'
    • 好的,所以,以这种方式管理事件比经典的“dom 附件”更轻松:) ..谢谢!
    • @steweb - 它也更轻,因为 jquery 不需要对所有 li 元素进行初始查找。它只是查找容器并在该级别侦听以查看单击的对象是否为 li。
    • 这个 .index 方法对我很有帮助。我正在使用 jQuery Sortable 进行排序,但它将语义排名信息存储在 DOM 中。使用 .index(),我可以非常干净地将排名从 dom 中拉出来。谢谢!
    【解决方案2】:

    类似:

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

    【讨论】:

    • 很好的补充——我们可以找到相对于父选择器的索引。 +1
    • 更喜欢这个答案,因为它实际上回答了问题,而不是示例的可能解决方案
    【解决方案3】:

    看看这个example

    $("#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>

      或者,如果子元素可能会动态变化(例如使用待办事项列表),那么您必须在每次点击时构造lis 数组,而不是事先构造:

      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 不是函数
      • 我的答案中的任何代码 sn-ps 都不会产生该错误 - 您可以按“运行代码 sn-p”来查看它们是否正常工作。如果您遇到该错误,则说明您使用的是不同的代码 - 听起来您使用的是 jQuery,但我的回答是展示如何在 without jQuery 的情况下完成这类事情
      • 很公平。是的,我正在使用 JQuery。谢谢
      【解决方案5】:

      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 delegate 不监控 dom。
      • @redsquare 我的印象是,Delegate 只是 Live 的一种更高效的变体。这来自api.jquery.com/delegate:“基于一组特定的根元素,为现在或将来匹配选择器的所有元素附加一个或多个事件的处理程序。”以后一定要监听才能绑定?
      • 不,它只是像上面的代码一样在容器上使用委托。如果你在容器中插入一个新的 li 元素,容器点击事件仍然会被触发并且一切仍然有效。无需监控。
      • @redsquare 是的,你是对的。即使在 DOM 加载后添加了新元素,我的解决方案也有效。由于 Delegate 在内部使用 Live(请参阅 stackoverflow.com/questions/2954932/…),它仍然感觉这更优化但不太方便。但正如我所说,我没有数字。
      【解决方案6】:

      另一种方式

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

      演示 https://jsfiddle.net/m9xge3f5/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-15
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 2013-06-13
        • 2014-12-12
        • 2013-12-28
        相关资源
        最近更新 更多