找到父节点中子节点索引的最快方法 [英] Fastest way to find the index of a child node in parent

查看:303
本文介绍了找到父节点中子节点索引的最快方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要找到具有id 'whereami'的子div的索引。

I want to find the index of the child div that has the id 'whereami'.

<div id="parent">
   <div></div>
   <div></div>
   <div id="whereami"></div>
   <div></div>
</div>

目前我正在使用此函数查找孩子的索引。

Currently I am using this function to find the index of the child.

function findRow(node){
    var i=1;
    while(node.previousSibling){
        node = node.previousSibling;
        if(node.nodeType === 1){
            i++;
        }
    }
    return i; //Returns 3
}

var node = document.getElementById('whereami'); //div node to find
var index = findRow(node);

fiddle: http://jsfiddle.net/grantk/F7JpH/2/

问题

当有数千个div节点时,while循环必须遍历每个div来对它们进行计数。可能需要一段时间。

The Problem
When there are a thousands of div nodes, the while loop has to traverse through each div to count them. Which can take a while.

有没有更快的方法来解决这个问题?

Is there any faster way to tackle this?

*请注意,将改为不同的div节点,所以需要重新计算。

*Note that the id will change to different divs node, so it will need to be able to re-calculate.

推荐答案

出于好奇我跑了你代码针对jQuery的 .index() 和我的下面的代码:

Out of curiosity I ran your code against both jQuery's .index() and my below code:

function findRow3(node)
{
    var i = 1;
    while (node = node.previousSibling) {
        if (node.nodeType === 1) { ++i }
    }
    return i;
}

跳转到jsperf结果

事实证明,jQuery大概减少了50%比你的实施(在Chrome / Mac上),我的可以说是1%。

It turns out that jQuery is roughly 50% slower than your implementation (on Chrome/Mac) and mine arguably topped it by 1%.

修改

不能让我这样做,所以我添加了两种方法:

Couldn't quite let this one go, so I've added two more approaches:

使用Array.indexOf

[].indexOf.call(node.parentNode.children, node);

改进了我以前的实验代码,如 HBP的答案 DOMNodeList 被视为一个数组,它使用 Array.indexOf() 确定其 .parentNode.children 中的所有元素的位置。我的第一次尝试是使用 .parentNode.childNodes ,但是由于文本节点导致错误的结果。

Improvement on my earlier experimental code, as seen in HBP's answer, the DOMNodeList is treated like an array and it uses Array.indexOf() to determine the position within its .parentNode.children which are all elements. My first attempt was using .parentNode.childNodes but that gives incorrect results due to text nodes.

使用previousElementSibling

user1689607的回答启发,最近的浏览器除了 .previousSibling 之外还有其他属性。 previousElementSibling ,它们都在一个原始语句中。 IE< = 8没有此属性,但 .previousSibling 已经这样做了,因此功能检测将工作。

Inspired by user1689607's answer, recent browsers have another property besides .previousSibling called .previousElementSibling, which does both original statements in one. IE <= 8 doesn't have this property, but .previousSibling already acts as such, therefore a feature detection would work.

(function() {
    // feature detection
    // use previousElementSibling where available, IE <=8 can safely use previousSibling
    var prop = document.body.previousElementSibling ? 'previousElementSibling' : 'previousSibling';

    getElementIndex = function(node) {
        var i = 1;
        while (node = node[prop]) { ++i }
        return i;
    }

结论

使用 IE浏览器不支持Array.indexOf(),仿真根本不够快,但是它的性能提升了20%

Using Array.indexOf() is not supported on IE <= 8 browsers, and the emulation is simply not fast enough; however, it does give 20% performance improvement.

使用功能检测和 .previousElementSibling 产生一个7x的提升(在Chrome上),我还没有在IE8上测试。

Using feature detection and .previousElementSibling yields a 7x improvement (on Chrome), I have yet to test it on IE8.

这篇关于找到父节点中子节点索引的最快方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆