90

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

UL
 LI
 LI
 LI - my index is 2
 LI

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

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

谢谢。

4

13 回答 13

106

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

于 2012-08-01T15:01:28.867 回答
72

这是我的做法(2018 版?)

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

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

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

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

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

于 2018-04-04T08:59:56.700 回答
54

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;
}
于 2012-08-01T15:37:03.637 回答
22
Array.prototype.indexOf.call(this.parentElement.children, this);

或使用let语句。

于 2016-01-18T21:41:56.347 回答
10

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

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

请注意,previousElementSiblingIE<9 不支持。

于 2014-12-17T08:49:49.503 回答
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]));
}​

JSFIDDLE

于 2012-08-01T14:55:16.693 回答
5

现代本机方法可以使用 '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>

`

于 2018-04-02T23:47:41.930 回答
2

从 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>
于 2015-09-29T17:07:02.450 回答
1

您可以遍历<li>s 中的 s<ul>并在找到正确的时停止。

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

}

演示

于 2012-08-01T15:01:44.170 回答
1

如果你想紧凑地写这个,你需要的是:

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

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

您还可以轻松地做到:

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

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

于 2016-10-04T20:37:35.833 回答
1
    const nodes = Array.prototype.slice.call( el.parentNode.childNodes );
    const index = nodes.indexOf(el);
    console.log('index = ', index);
于 2019-05-13T08:52:03.393 回答
0

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

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

于 2012-08-01T15:08:29.370 回答
0

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

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);
                }
            }
        }
    }
}
于 2012-08-01T15:08:55.883 回答