在jQuery中访问DOM元素的最有效方法是什么?

时间:2009-05-18 18:29:45

标签: javascript jquery

我正在编写一个jQuery插件,我正处于优化阶段。

我想知道其中哪些会导致更快的脚本,以及哪种缓解因素很重要:

  1. 让脚本在开始时生成大量的类和ID,以便在以后查找dom中的元素更容易(也更快?)。
  2. 将类和ID保持在最低限度(这样可以通过不创建它们来节省时间),但之后会以更复杂的方式查找元素(例如,对象中的第n项),我认为这比获取id /更慢类。

4 个答案:

答案 0 :(得分:12)

浏览器的工作方式是在加载时创建一个内存中的DOM树,如下所示:

                                              P
                               _______________|______________
                              |                              |
                          childNodes                    attributes
                ______________|___________                   |
               |              |           |            title = 'Test paragraph'
         'Sample of text '   DIV   'in your document'
                              |
                          childNodes
                    __________|_______
                   |          |       |
           'HTML you might'   B     'have'

因此,当您查找P > DIV > B时,查找必须找到所有P元素,然后查找P中的所有DIV元素,然后查找DIV中的所有B元素。嵌套越深,它需要执行的查找越多。此外,它可能会发现所有P > DIV只发现它们都没有B,并且会浪费时间查看所有P > DIV个匹配项。

ID查找速度更快,因为ID保证是唯一的,因此DOM可以将它们存储为具有非常快速查找的哈希表条目。就jQuery而言,实现可能略有不同,但是,document.getElementById具有最快的查找时间,因此$('#my_node_id')也应该非常快。

因此,如果您的节点没有ID,您可以找到最近的祖先,并找到相对于该祖先的节点

#my_node_id > div > b

因为查找只需要在#my_node_id的子树下进行,它会比p > div > b更快

答案 1 :(得分:11)

这个问题不够具体,所以我可以给你直接与你的代码相关的建议,但这里有一些我最喜欢的jQuery优化技巧:

  1. 尽可能指定上下文!不要让jQuery看起来不必要的地方。如果你知道某些内容会出现在#container div中,请执行$(something, '#container');
  2. .myclass 。在内部,jQuery必须通过每个元素来查看它是否具有您要搜索的类,至少对于那些不支持getElementsByClassName的浏览器而言。如果您知道某个类只会应用于某个元素,那么{em>方式可以更快地执行tag.myclass,因为jQuery可以使用本机getElementsByTagName并仅搜索那些。
  3. 不要在一次爆炸中做复杂的选择器。当然,jQuery可以找出你想要的东西,但是需要时间来解析字符串并应用你想要的逻辑。因此,我总是喜欢把我的“查询”分成补丁。虽然大多数人可能会$('#myform input:eq(2)');或类似的事情,但我更愿意$('input','#myform').eq(2);来帮助jQuery。
  4. 如果您计划使用一组对象执行多项操作,请不要重新查询DOM。利用链接的优势,如果由于某种原因无法使用链接,请将查询结果缓存到变量中并对其执行调用。

答案 2 :(得分:5)

我认为你回答了自己的问题:'复杂的方式'是'它会破坏'的同义词 - 对html结构的任何更改都会破坏你的代码。

例如,假设您尝试获取myDiv,并认为它是child的最后一个兄弟:

<div>parent
     <div>child</div>
     <div>myDiv</div>
</div>

如果您稍后决定结构应该是这样的话,会发生什么?

<div>parent
     <div>child</div>
     <div>myDiv</div>
     <div>child</div>
</div>

依靠关于结构的假设,你的代码变得非常脆弱。向节点添加类和ID将防止出现这种情况。

我认为你应该选择第一选择。还要记住,按类获取节点总是慢于通过id获取节点。

答案 3 :(得分:3)

使用我的插件,我尽可能地尝试限制我在文档中引入的钩子数量。 “钩子”我的意思是ID或类。

完全避免它们的最佳方法是保留对插件闭包中任何已创建元素的引用。例如:

jQuery.fn.addList = function(items, fn){
    var $list = $('<ul/>').html('<li>' + items.join('</li><li>') + '</li>');
    return this.each(function(){
        $(this).append($list);
        fn.call($list);
    });
};

$('body').addList(['item 1', 'item 2'], function(){
    var referenceToTheList = this;
    console.log(referenceToTheList, '<- this is my list, no hooks involved!');
});

该列表可以围绕JavaScript函数(在多个地方引用和使用)进行,而不需要HTML中的任何钩子;从而使它尽可能不引人注目!

避免/限制挂钩在插件开发中尤其重要,因为你永远不知道它最终会被用在哪里。