JavaScript DOM:在容器中查找元素索引
Posted
技术标签:
【中文标题】JavaScript DOM:在容器中查找元素索引【英文标题】:JavaScript DOM: Find Element Index In Container 【发布时间】: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 元素会很容易。例如、 ,你可以轻松访问。 【参考方案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】:您可以遍历<ul>
中的<li>
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
【讨论】:
我误解了这个问题。已编辑!previousElementSibling
solution 更好,因为它将排除文本节点并返回您期望的元素的索引。以上是关于JavaScript DOM:在容器中查找元素索引的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript 学习-27.查找HTML DOM节点(元素)
使用 JavaScript 获取 2 个 DOM 元素之间的相对位置