【问题标题】:What is the most efficient way to access DOM elements in jQuery?在 jQuery 中访问 DOM 元素的最有效方法是什么?
【发布时间】:2009-05-18 18:29:44
【问题描述】:

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

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

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

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    浏览器的工作方式是在加载时创建一个内存中的 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更快

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        我认为您回答了您自己的问题:“复杂的方式”是“它会破坏”的同义词 - 对 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 获取节点慢。

        【讨论】:

          【解决方案4】:

          我尽量使用我的插件来限制我在文档中引入的钩子的数量。 “钩子”是指 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 中的任何钩子;从而使其尽可能不引人注目!

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

          【讨论】:

            猜你喜欢
            • 2019-06-30
            • 2014-09-24
            • 2011-07-17
            • 1970-01-01
            • 2014-11-29
            • 2012-05-22
            • 2010-09-24
            • 1970-01-01
            • 2016-01-16
            相关资源
            最近更新 更多