我需要通过对象引用在其容器内找到元素的索引。奇怪的是,我找不到简单的方法。请不要jQuery-只有DOM。
UL
LI
LI
LI - my index is 2
LI
是的,我可以为每个元素分配ID并遍历所有节点以匹配ID,但这似乎是一个不好的解决方案。没有更好的东西吗?
因此,就像上面的示例一样,我有一个对第三LI的对象引用。我怎么知道它是索引2?
谢谢。
我需要通过对象引用在其容器内找到元素的索引。奇怪的是,我找不到简单的方法。请不要jQuery-只有DOM。
UL
LI
LI
LI - my index is 2
LI
是的,我可以为每个元素分配ID并遍历所有节点以匹配ID,但这似乎是一个不好的解决方案。没有更好的东西吗?
因此,就像上面的示例一样,我有一个对第三LI的对象引用。我怎么知道它是索引2?
谢谢。
Answers:
您可以使用Array.prototype.indexOf
。为此,我们需要在某种程度上“铸成” HTMLNodeCollection
true 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
解决方案更好,因为它将排除文本节点,并返回所需元素的索引。
const index = [...el.parentNode.children].indexOf(el)
Array.from( el.parentNode.children ).indexOf( el );
,出于可读性考虑,我实际上更喜欢这种情况。
2017更新
下面的原始答案假设OP希望包含非空文本节点和其他节点类型以及元素。现在从这个问题上对我来说还不清楚,这是否是一个有效的假设。
假设您只需要元素索引,previousElementSibling
现在它得到了很好的支持(2012年不是这种情况),并且现在是显而易见的选择。以下内容(与此处的其他一些答案相同)将在除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;
}
这是我的工作方式(2018版本?):
const index = [...el.parentElement.children].indexOf(el);
他达安 而且,如果您也想考虑原始文本节点,可以改为执行以下操作:
const index = [...el.parentElement.childNodes].indexOf(el);
我将这些子项分散为一个数组,因为它们是HTMLCollection(因此它们不能与indexOf一起使用)。
请注意,您正在使用Babel或浏览器的覆盖范围足以满足您需要实现的目标(有关散布运算符的想法,基本上是从后台进行的Array。)。
Array.from
分别添加到childNodes中const index = [...Array.from(el.parentElement.children)].indexOf(el);
对于仅元素,可以使用它在同级元素之间查找元素的索引:
function getElIndex(el) {
for (var i = 0; el = el.previousElementSibling; i++);
return i;
}
请注意,previousElementSibling
IE <9不支持该功能。
您可以使用它来查找元素的索引:
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]));
}
previousElementSibling
解决方案更好,因为它将排除文本节点,并返回所需元素的索引。
现代的本机方法可以利用'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>
`
从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>
另一个仅使用基本循环和索引检查的示例
的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;
}
运行示例
只需将对象引用传递给以下函数,您将获得索引
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);
}
}
}
}
}