JavaScript DOM:在容器中查找元素索引

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

UL LI LI LI - my index is 2 LI 

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

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

谢谢。

你可以使用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> 

2017更新

下面的原始答案假定OP想要包含非空文本节点和其他节点types以及元素。 从现在的问题来看,这是否是一个有效的假设呢?

假设你只想要元素索引,那么previousElementSibling现在可以得到很好的支持(在2012年情况并非如此),而且现在是明显的select。 以下(与其他一些答案相同)将在除IE <= 8之外的所有主要内容中工作。

 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; } 

你可以用它来find一个元素的索引:

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

这例如logging所有的指标:

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

的jsfiddle

对于只是元素,这可以用来find它的兄弟元素中的一个元素的索引:

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

请注意,IE <9中不支持previousElementSibling

 Array.prototype.indexOf.call(this.parentElement.children, this); 

或者使用let语句。

从HTMLCollection创build数组的一个示例

 <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> 

另一个例子只是使用基本的循环和索引检查

HTML

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

JavaScript 运行onload / ready或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

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

 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); } } } } } 

如果你想写这个紧凑的所有你需要的是:

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

我们只是遍历父节点中的元素,当我们find你的元素时停下来。

你也可以轻松做到:

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

如果这只是你想要通过。

您可以遍历<ul><li> ,并在find正确的时候停止。

 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; } } } 

演示