获得dom元素的最快方法是什么?

时间:2009-04-03 15:13:01

标签: javascript jquery dom

我正在对我的代码进行性能调优,并且很惊讶地发现瓶颈不是dom节点插入,而是选择。

这很快:

var row = jquery(rowHTML).appendTo(oThis.parentTable);

但随后在“行”中获取元素的速度很慢:

var checkbox = jquery(".checkbox input", row);

我需要获取每一行的复选框,以便我可以附加一个事件处理程序。选择该复选框是ALMOST 10X AS SLOW,因为插入整个父行。

我在这里做错了什么?

7 个答案:

答案 0 :(得分:13)

DOM操作使用本机函数来执行简单操作。浏览器厂商优化这些。您正在从HTML构建行。在内部,jQuery使用.innerHTML来构建集合,然后将其修补到浏览器的超快速解析器中。

选择比较慢,因为JS代码需要重复遍历DOM。较新的浏览器具有本机选择处理功能,可为基于选择器的JS提供显着的加速。随着时间的推移,这将不再是一个问题。

以下是有问题的查询$(".checkbox input", row)如何分解:

  1. row.getElementsByTagName('*');
  2. for循环遍历返回的每个元素(行中的所有元素)并使用elements[i].className测试/(\s|^)checkbox(\s|$)/
  3. for循环每个仍然存在的元素并收集matched[i].getElementsByTagName('input');
  4. 独特的最终系列。
  5. 这与jQuery 1.3不同,因为它的引擎以相反的方式在选择器中移动,从获取所有输入元素开始,然后测试父元素。

    Rremember认为,JS选择器引擎实现了比CSS实际可用(或当前浏览器实现)更多的CSS选择器规范。利用这一点,以及对引擎的了解,我们可以通过几种不同的方式优化选择器:

    如果你知道.checkbox是什么元素类型:

    $("td.checkbox input", row);
    

    首先对类型进行过滤,然后对于仅对那些匹配进行类更快。这不适用于非常小的元素子集,但在实践中几乎不是这种情况。

    单一类测试是常见selectors people actually use中最慢的。

    更简单的选择:

    $("input[type=checkbox]", row);
    

    一个循环比两个循环快。这只找到输入元素,然后直接按类型属性过滤它们。由于从不使用sub / child-elements,因此也可以跳过unique(并且智能引擎会尝试执行此操作,因为unique很慢)。

    更直接的选择器:

    $("td:first.checkbox input", row);
    

    如果更复杂的选择器更直接(YMMV),它实际上可能更快。

    如果可能,请将搜索上下文移至表级:

    我的意思是,不是循环遍历行,而是搜索每个行中的复选框,不要将它们留在循环之后,然后一次选择它们:

    $("tr td:first.checkbox input", table);
    

    这样做的目的是消除重复启动选择器引擎的开销,而是一次性完成所有操作。这里提供的是完整性,而不是我认为会带来大量加速的东西。

    请勿选择:

    从位构建行,随时分配事件。

    var row = $( '<tr></tr>' );
    var cell = $( '<td class="checkbox"></td>' ).appendTo( row );
    $( '<input type="checkbox" name="..."/>' ).appendTo( cell ).click(/* ... */);
    

    由于Ajax或其他模板无法控制,这可能是不可能的。此外,速度可能不值得将您的代码变成这种混乱,但有时这可能是有道理的。

    或者,如果这些都不适合您,或者返回太多的性能增益,那么可能是时候重新考虑该方法了。您可以在树的上方分配一个事件侦听器并在那里获取事件,而不是每个元素实例:

    $('table').change(function(e){
      // you may want a faster check...
      if ( $(e.target).is('input[type=checkbox]') ) {
        // do some stuff ...
      }
    });
    

    这样,除非用户实际请求,否则您不会执行任何操作。最快的。 : - )

答案 1 :(得分:2)

var checkbox = jquery(".checkbox input", row);

这是遍历整个dom树以找到复选框。您可以通过将选择器更改为可以使用浏览器本机getElementById功能的ID来加快速度。

var checkbox = jquery("#checkbox input", row);

您也可以使用行作为DOM搜索的起点,如下例所示。现在你不再遍历整个DOM树来找到匹配的元素。

var row = jquery(rowHTML).appendTo(oThis.parentTable);
row.children(".checkbox input");

答案 2 :(得分:2)

使用事件委托并将单个处理程序添加到父元素,而不是复选框本身。

jQuery通过live()函数支持此功能。

答案 3 :(得分:1)

尝试在输入字段上放置一个类名。这可能会更快。

原因是您的代码遍历所有.checkbox类,尝试查找该元素的输入子元素并返回该元素。我认为这个行动可能是你的罪魁祸首。

通过简单地只查找输入字段所具有的类的所有元素,您可能会看到一些加速。

答案 4 :(得分:1)

尝试使用Sly,它强调性能。

答案 5 :(得分:0)

如果你正在寻找性能,jQuery选择器非常慢。在那里的示例中,它必须扫描完整的DOM树并检查CSS类等,以找到相关的节点。

使用本机DOM方法要快得多。这里有一些有趣的库性能比较:

http://ajaxian.com/archives/taskspeed-more-benchmarks-for-the-libraries-and-browsers

答案 6 :(得分:0)

获取DOM元素的最快方法是使用纯JavaScript并通过ID调用它。

// This results in a blank image on the button
customCell.myButton.imageView?.contentMode = .ScaleAspectFit
customCell.myButton.imageView?.image = buttonImage