【问题标题】:JavaScript DOM: Find Element Index In ContainerJavaScript DOM:在容器中查找元素索引
【发布时间】:2012-07-30 12:06:41
【问题描述】:

我需要通过对象引用在其容器内找到元素的索引。奇怪的是,我找不到简单的方法。请不要使用 jQuery - 只有 DOM。

UL
 LI
 LI
 LI - my index is 2
 LI

是的,我可以为每个元素分配 ID 并遍历所有节点以匹配 ID,但这似乎是一个糟糕的解决方案。没有更好的东西吗?

所以,假设我有一个对第三个 LI 的对象引用,如上例所示。我怎么知道它是索引 2?

谢谢。

【问题讨论】:

  • 需要如何获取索引?悬停..等??
  • 为什么不在 li 引用上执行 previousSibling 直到你命中 null?
  • Finding DOM node index 的可能重复项
  • 我认为如果您将自定义属性添加到 li 元素会很容易。例如
  • ,你可以轻松访问。

标签: javascript html dom parent-child


【解决方案1】:
    const nodes = Array.prototype.slice.call( el.parentNode.childNodes );
    const index = nodes.indexOf(el);
    console.log('index = ', index);

【讨论】:

    【解决方案2】:

    这是我的做法(2018 版?)

    const index = [...el.parentElement.children].indexOf(el);
    

    Tadaaaam。而且,如果你也想考虑原始文本节点,你可以这样做:

    const index = [...el.parentElement.childNodes].indexOf(el);
    

    我将孩子分散到一个数组中,因为它们是一个 HTMLCollection(因此它们不适用于 indexOf)。

    请注意您正在使用 Babel,或者浏览器覆盖范围足以满足您的需要(考虑扩展运算符,它基本上是一个 Array.from 幕后)。

    【讨论】:

    • 可以确认这是有效的。无需循环任何内容。
    • 最佳答案 IMO,简洁明了
    • 真的很酷!刚刚将Array.from分别添加到childNodes const index = [...Array.from(el.parentElement.children)].indexOf(el);
    • 如果用作采访的一部分 - 你应该提到 Array.from (或 [...] )将创建集合的浅表副本 - 而 Array.prototype.indexOf.call 不会。
    • 当使用 [...el.parentElement.children] 和 typescript 时,会引发错误:Type 'HTMLCollection' 不是数组类型或没有返回的 '[Symbol.iterator]()' 方法一个迭代器。 在这种情况下,这种方法更好:Array.from(el.parentElement.children)
    【解决方案3】:

    现代原生方法可以使用 'Array.from()' - 例如:`

    const el = document.getElementById('get-this-index')
    const index = Array.from(document.querySelectorAll('li')).indexOf(el)
    document.querySelector('h2').textContent = `index = ${index}`
    <ul>
      <li>zero
      <li>one
      <li id='get-this-index'>two
      <li>three
    </ul>
    <h2></h2>

    `

    【讨论】:

      【解决方案4】:

      您可以遍历&lt;ul&gt; 中的&lt;li&gt;s,并在找到合适的时候停止。

      function getIndex(li) {
          var lis = li.parentNode.getElementsByTagName('li');
          for (var i = 0, len = lis.length; i < len; i++) {
              if (li === lis[i]) {
                  return i;
              }
          }
      
      }
      

      Demo

      【讨论】:

        【解决方案5】:

        您可以使用Array.prototype.indexOf。为此,我们需要将HTMLNodeCollection 稍微“转换”为真正的Array。例如:

        var nodes = Array.prototype.slice.call( document.getElementById('list').children );
        

        那么我们可以直接调用:

        nodes.indexOf( liNodeReference );
        

        例子:

        var nodes = Array.prototype.slice.call( document.getElementById('list').children ),
            liRef = document.getElementsByClassName('match')[0];
        
        console.log( nodes.indexOf( liRef ) );
        <ul id="list">
            <li>foo</li>
            <li class="match">bar</li>
            <li>baz</li>    
        </ul>

        【讨论】:

        • 注意:.childNodes.children 是不同的东西。 .children 是一个子集,只是所有 ElementNodes 的列表。
        • previousElementSibling solution 更好,因为它将排除文本节点并返回您期望的元素的索引。
        • ES6 语法:const index = [...el.parentNode.children].indexOf(el)
        • 我实际上更喜欢 Array.from( el.parentNode.children ).indexOf( el ); 在那个实例上,只是为了可读性。
        【解决方案6】:

        2017 年更新

        下面的原始答案假设 OP 希望包含非空文本节点和其他节点类型以及元素。现在我似乎不清楚这是否是一个有效的假设。

        假设您只需要元素索引,previousElementSibling 现在得到了很好的支持(2012 年不是这种情况),现在是显而易见的选择。以下(与此处的其他一些答案相同)将适用于除 IE

        function getElementIndex(node) {
            var index = 0;
            while ( (node = node.previousElementSibling) ) {
                index++;
            }
            return index;
        }
        

        原答案

        只需使用previousSibling,直到您点击null。我假设您想忽略纯空格文本节点;如果要过滤其他节点,请相应调整。

        function getNodeIndex(node) {
            var index = 0;
            while ( (node = node.previousSibling) ) {
                if (node.nodeType != 3 || !/^\s*$/.test(node.data)) {
                    index++;
                }
            }
            return index;
        }
        

        【讨论】:

        • +1 与此处描述的任何其他方法相比,这是最快的。对于较新的浏览器,previousElementSibling 可以在没有这两个条件的情况下使用。
        • @bjb568:你的意思是有一组不必要的括号吗?
        • 没有必要。这不够。每个人都知道,为了美丽,你至少需要另外 7 个。
        • @bjb568:最好也关闭它们。
        • 这 !/^\s*$/.test(node.data) 到底是做什么的?
        【解决方案7】:

        如果你想写得紧凑,你只需要:

        var i = 0;
        for (;yourElement.parentNode[i]!==yourElement;i++){}
        indexOfYourElement = i;
        

        我们只是循环遍历父节点中的元素,当我们找到您的元素时停止。

        您也可以轻松地这样做:

        for (;yourElement.parentNode.getElementsByTagName("li")[i]!==yourElement;i++){}
        

        如果这就是你想要查看的全部内容。

        【讨论】:

          【解决方案8】:
          Array.prototype.indexOf.call(this.parentElement.children, this);
          

          或者使用let 声明。

          【讨论】:

          • @citykid,当然,它更简洁,但创建一个临时数组只是为了访问该数组的函数是愚蠢的。
          【解决方案9】:

          从 HTMLCollection 制作数组的示例

          <ul id="myList">
              <li>0</li>
              <li>1</li>
              <li>2</li>
              <li>3</li>
              <li>4</li>
          </ul>
          
          <script>
          var tagList = [];
          
          var ulList = document.getElementById("myList");
          
          var tags   = ulList.getElementsByTagName("li");
          
          //Dump elements into Array
          while( tagList.length != tags.length){
              tagList.push(tags[tagList.length])
          };
          
          tagList.forEach(function(item){
                  item.addEventListener("click", function (event){ 
                      console.log(tagList.indexOf( event.target || event.srcElement));
                  });
          }); 
          </script>
          

          【讨论】:

            【解决方案10】:

            仅对于元素,这可用于在其兄弟元素中查找元素的索引:

            function getElIndex(el) {
                for (var i = 0; el = el.previousElementSibling; i++);
                return i;
            }
            

            注意previousElementSibling 在 IE

            【讨论】:

            • 如果不是上一个兄弟而是下一个怎么办?
            • @RooticalV.:不确定你的意思。你的意思是问如果没有以前的兄弟姐妹会发生什么?在这种情况下,循环将自动退出,因为表达式“el = el.previousElementSibling”的值将是假的(因为它是空的)。或者你的意思是问如果你在上面的代码中将“previousElementSibling”替换为“nextElementSibling”会发生什么?好吧,在这种情况下,循环将计算仍然跟随元素的兄弟姐妹的数量。
            【解决方案11】:

            只需将对象引用传递给以下函数即可获得索引

            function thisindex(elm) 
            { 
                var the_li = elm; 
                var the_ul = elm.parentNode; 
                var li_list = the_ul.childNodes; 
            
                var count = 0; // Tracks the index of LI nodes
            
                // Step through all the child nodes of the UL
                for( var i = 0; i < li_list.length; i++ )
                {
                    var node = li_list.item(i);
                    if( node )
                    {
                    // Check to see if the node is a LI
                        if( node.nodeName == "LI" )
                        {
                        // Increment the count of LI nodes
                            count++;
                        // Check to see if this node is the one passed in
                            if( the_li == node )
                            {
                                // If so, alert the current count
                                alert(count-1);
                            }
                        }
                    }
                }
            }
            

            【讨论】:

              【解决方案12】:

              另一个仅使用基本循环和索引检查的示例

              HTML

              <ul id="foo">
                  <li>0</li>
                  <li>1</li>
                  <li>2</li>
                  <li>3</li>
                  <li>4</li>
              </ul>
              

              JavaScript 在加载/就绪或 ul 渲染后运行

              var list = document.getElementById("foo"),
                  items = list.getElementsByTagName("li");
              
              list.onclick = function(e) {
                  var evt = e || window.event,
                  src = evt.target || evt.srcElement;
                  var myIndex = findIndex(src);
                  alert(myIndex);
              };
              
              function findIndex( elem ) {
                  var i, len = items.length;
                  for(i=0; i<len; i++) {
                      if (items[i]===elem) {
                          return i;
                      }
                  }
                  return -1;
              }
              

              运行示例

              jsFiddle

              【讨论】:

                【解决方案13】:

                您可以使用它来查找元素的索引:

                Array.prototype.indexOf.call(yourUl, yourLi)

                这例如记录所有索引:

                var lis = yourList.getElementsByTagName('li');
                for(var i = 0; i < lis.length; i++) {
                    console.log(Array.prototype.indexOf.call(lis, lis[i]));
                }​
                

                JSFIDDLE

                【讨论】:

                猜你喜欢
                相关资源
                最近更新 更多
                热门标签