这篇文章是jQuery各种 show/hide方式的性能测试。作者之所以测试这个源于Robert Duffy在SanFrancisco举行的jQuery大会上的一句话:“.hide()和.show()的执行速度会比直接改变css慢”。但由于未能找RobertDuffy问明原因,所以作者就自己去做了这个测试。下面的翻译并不是全文翻译,只节选了一些重点。

用作测试的是一个含有100个div的HTML页面,div带有 class和一些内容。为了排除掉寻找这些div所花费的时间,所以把选择器$('div')缓存起来了。用作测试的jQuery版本是1.4.2,所以测试结果也只是针对这个版本,在其他版本可能就不是这些结果了。
测试的jQuery方法分别是:

  • .toggle()
  • .show() 和 .hide()
  • .css({'display':'none'}) 和 .css({'display':'block'})
  • .addClass('hide') 和 .removeClass('hide')
  • 改变<style>元素的一个属性

在所有浏览器中,这两个方法在隐藏DOM元素上相对来说比较慢。主要原因在于.hide()方法必须先保存元素的"display"属性,这样.show()才能把元素恢复到原来的状态。这里用到了.data()这个 jQuery方法,把信息保存在DOM元素上。为了达到这个目的,.hide()在每个元素上循环了两次,一次用来保存当前的"display"值,一次用来更新样式"display"为"none"。根据源代码上的注释,这样做是为了防止浏览器在每个循环上进行重新渲染(reflow)。.hide() 方法还会检查你是否传递了使用动画效果的参数,就算传入一个"0"也会让性能大打折扣。在第一次调用.hide()的时候性能最慢,在之后再调用则会变快。 
在所有浏览器中,这两个方法在隐藏DOM元素上相对来说比较慢。主要原因在于.hide()方法必须先保存元素的"display"属性,这样.show()才能把元素恢复到原来的状态。这里用到了.data()这个 jQuery方法,把信息保存在DOM元素上。为了达到这个目的,.hide()在每个元素上循环了两次,一次用来保存当前的"display"值,一次用来更新样式"display"为"none"。根据源代码上的注释,这样做是为了防止浏览器在每个循环上进行重新渲染(reflow)。.hide() 方法还会检查你是否传递了使用动画效果的参数,就算传入一个"0"也会让性能大打折扣。在第一次调用.hide()的时候性能最慢,在之后再调用则会变快。 
在所有浏览器中,这两个方法在隐藏DOM元素上相对来说比较慢。主要原因在于.hide()方法必须先保存元素的"display"属性,这样.show()才能把元素恢复到原来的状态。这里用到了.data()这个 jQuery方法,把信息保存在DOM元素上。为了达到这个目的,.hide()在每个元素上循环了两次,一次用来保存当前的"display"值,一次用来更新样式"display"为"none"。根据源代码上的注释,这样做是为了防止浏览器在每个循环上进行重新渲染(reflow)。.hide() 方法还会检查你是否传递了使用动画效果的参数,就算传入一个"0"也会让性能大打折扣。在第一次调用.hide()的时候性能最慢,在之后再调用则会变快。

Browser hide/show
FireFox 3.6 29ms / 10ms
Safari 4.05 6ms / 1ms
Opera 10.10 9ms / 1ms
Chrome 5.0.3 5ms / 1ms
IE 6.0 31ms / 16ms
IE 7.0 15ms / 16ms

这个方法是最慢的。它会检查选择器返回的每一个元素当前是否可见,如果可见的话就调用.hide()方法,不可见则调用.show()方法。不但如此,它不仅会检查你是否传递了一个boolean值进去阻止.hide()或者.show()的执行,还会检查看你是否传入了function来进行切换(toggle)而不是对可见性进行切换。看起来这个方法还有很大的改善空间,例如可以先一次过把隐藏的元素select出来,然后调用.show()方法,同时把其余的元素select出来调用.hide()方法。 
这个方法是最慢的。它会检查选择器返回的每一个元素当前是否可见,如果可见的话就调用.hide()方法,不可见则调用.show()方法。不但如此,它不仅会检查你是否传递了一个boolean值进去阻止.hide()或者.show()的执行,还会检查看你是否传入了function来进行切换(toggle)而不是对可见性进行切换。看起来这个方法还有很大的改善空间,例如可以先一次过把隐藏的元素select出来,然后调用.show()方法,同时把其余的元素select出来调用.hide()方法。 
这个方法是最慢的。它会检查选择器返回的每一个元素当前是否可见,如果可见的话就调用.hide()方法,不可见则调用.show()方法。不但如此,它不仅会检查你是否传递了一个boolean值进去阻止.hide()或者.show()的执行,还会检查看你是否传入了function来进行切换(toggle)而不是对可见性进行切换。看起来这个方法还有很大的改善空间,例如可以先一次过把隐藏的元素select出来,然后调用.show()方法,同时把其余的元素select出来调用.hide()方法。

Browser hide/show
FireFox 3.6 80ms / 59ms
Safari 4.05 24ms / 30ms
Opera 10.10 67ms / 201ms
Chrome 5.0.3 55ms / 20ms
IE 6.0 296ms / 78ms
IE 7.0 328ms / 47ms

这是两个很漂亮的隐藏/显示DOM元素方法。在Firefox上它的速度是.show() 和.hide()的两倍,而在Safari上则是三倍。不过在IE6,IE7,Chrome和Opera上,两种方法几乎没什么差别。值得一提的是,对于 100个DOM节点来说,两种方法在Firefox上相差18ms,在Safari相差4ms,速度的差异只会体现在大量节点选择的时候。不过增加和移除 class需要你花费更多的工作,因为你需要创建一个用于隐藏的class,然后还要时刻关注着这个class的优先级以保证DOM能隐藏。jQuery 增加和移除class是通过字符串操作的,所以我觉得随着元素上class数量的增加,这个方法会变慢,但是我还没对此进行测试过。 
这是两个很漂亮的隐藏/显示DOM元素方法。在Firefox上它的速度是.show() 和.hide()的两倍,而在Safari上则是三倍。不过在IE6,IE7,Chrome和Opera上,两种方法几乎没什么差别。值得一提的是,对于 100个DOM节点来说,两种方法在Firefox上相差18ms,在Safari相差4ms,速度的差异只会体现在大量节点选择的时候。不过增加和移除 class需要你花费更多的工作,因为你需要创建一个用于隐藏的class,然后还要时刻关注着这个class的优先级以保证DOM能隐藏。jQuery 增加和移除class是通过字符串操作的,所以我觉得随着元素上class数量的增加,这个方法会变慢,但是我还没对此进行测试过。 
这是两个很漂亮的隐藏/显示DOM元素方法。在Firefox上它的速度是.show() 和.hide()的两倍,而在Safari上则是三倍。不过在IE6,IE7,Chrome和Opera上,两种方法几乎没什么差别。值得一提的是,对于 100个DOM节点来说,两种方法在Firefox上相差18ms,在Safari相差4ms,速度的差异只会体现在大量节点选择的时候。不过增加和移除 class需要你花费更多的工作,因为你需要创建一个用于隐藏的class,然后还要时刻关注着这个class的优先级以保证DOM能隐藏。jQuery 增加和移除class是通过字符串操作的,所以我觉得随着元素上class数量的增加,这个方法会变慢,但是我还没对此进行测试过。

Browser hide/show
FireFox 3.6 11ms / 11ms
Safari 4.05 2ms / 2ms
Opera 10.10 6ms / 3ms
Chrome 5.0.3 3ms / 1ms
IE 6.0 47ms / 32ms
IE 7.0 15ms / 16ms

这两个方法也很漂亮。相对于.addClass() 和.removeClass(),IE6/7和Opera上的速度都得到了提升,而在其他浏览器上则能保持水准。当你知道要改变的元素的当前 display样式,或者没有通过inline的方式去改变元素的display样式时,这两个方法很好用。如果你通过inline的方式改变了 display样式,那么你需要确保在使得元素重新可见时display值要设置正确。如果你只是使用了元素的默认display值或者在css里设置 display值,那么你只需要用类似.css({'display':''})的方法移除样式,元素就会恢复到它在css上的样式或者默认display值。作为一个类库,jQuery不能假定元素的display不是通过inline方式设置的,所以它需要被人手的去确定。不过既然你知道你不会去inline的设置display,那么你就可以去避免这个造成缓慢的主要因素。 
这两个方法也很漂亮。相对于.addClass()和.removeClass(),IE6/7和Opera上的速度都得到了提升,而在其他浏览器上则能保持水准。当你知道要改变的元素的当前display样式,或者没有通过inline的方式去改变元素的display样式时,这两个方法很好用。如果你通过inline的方式改变了display样式,那么你需要确保在使得元素重新可见时display值要设置正确。如果你只是使用了元素的默认 display值或者在css里设置display值,那么你只需要用类似.css({'display':''})的方法移除样式,元素就会恢复到它在 css上的样式或者默认display值。作为一个类库,jQuery不能假定元素的display不是通过inline方式设置的,所以它需要被人手的去确定。不过既然你知道你不会去inline的设置display,那么你就可以去避免这个造成缓慢的主要因素。 
这两个方法也很漂亮。相对于.addClass()和.removeClass(),IE6/7和Opera上的速度都得到了提升,而在其他浏览器上则能保持水准。当你知道要改变的元素的当前display样式,或者没有通过inline的方式去改变元素的display样式时,这两个方法很好用。如果你通过inline的方式改变了display样式,那么你需要确保在使得元素重新可见时display值要设置正确。如果你只是使用了元素的默认 display值或者在css里设置display值,那么你只需要用类似.css({'display':''})的方法移除样式,元素就会恢复到它在 css上的样式或者默认display值。作为一个类库,jQuery不能假定元素的display不是通过inline方式设置的,所以它需要被人手的去确定。不过既然你知道你不会去inline的设置display,那么你就可以去避免这个造成缓慢的主要因素。

Browser hide/show
FireFox 3.6 14ms / 12ms
Safari 4.05 2ms / 1ms
Opera 10.10 2ms / 2ms
Chrome 5.0.3 2ms / 1ms
IE 6.0 16ms / 16ms
IE 7.0 0ms / 0ms // 少于15ms会变成0ms

纯粹为了好玩,我想:如果我们不在每个dom节点上花功夫,而是去捣鼓样式表会怎样呢?这样会提高速度吗?其实就日常使用来说,上面的测试用到的方法已经足够快了,但是如果页面上有10000个节点需要进行隐藏和显示呢?只是把它们全部选择出来就已经够慢了。如果我可以控制样式表,那么就可以完全避免这些时间花费了。不过我得告诉你,这个方法是有很大风险的。 
风险在于控制样式表时的跨浏览器问题。首先,我尝试能不能通过jQuery插入一个带有class的"style"标签,但是却出现了跨浏览器问题。然后我尝试用javascript去创建stylesheet节点和class,但是实在有太多的API了,要搞清楚需要花不少的时间。最后,放弃了编程的方式,我在head区里写了一个带有class的style标签。通过编程的方式来创建stylesheet实在是太慢了,但是如果它一旦被创建好,那么给它一个ID和使用它的"disabled"属性就是轻而易举的事情了。 
纯粹为了好玩,我想:如果我们不在每个dom节点上花功夫,而是去捣鼓样式表会怎样呢?这样会提高速度吗?其实就日常使用来说,上面的测试用到的方法已经足够快了,但是如果页面上有10000个节点需要进行隐藏和显示呢?只是把它们全部选择出来就已经够慢了。如果我可以控制样式表,那么就可以完全避免这些时间花费了。不过我得告诉你,这个方法是有很大风险的。 
风险在于控制样式表时的跨浏览器问题。首先,我尝试能不能通过jQuery插入一个带有class的"style"标签,但是却出现了跨浏览器问题。然后我尝试用javascript去创建stylesheet节点和class,但是实在有太多的API了,要搞清楚需要花不少的时间。最后,放弃了编程的方式,我在head区里写了一个带有class的style标签。通过编程的方式来创建stylesheet实在是太慢了,但是如果它一旦被创建好,那么给它一个ID和使用它的"disabled"属性就是轻而易举的事情了。 
纯粹为了好玩,我想:如果我们不在每个dom节点上花功夫,而是去捣鼓样式表会怎样呢?这样会提高速度吗?其实就日常使用来说,上面的测试用到的方法已经足够快了,但是如果页面上有10000个节点需要进行隐藏和显示呢?只是把它们全部选择出来就已经够慢了。如果我可以控制样式表,那么就可以完全避免这些时间花费了。不过我得告诉你,这个方法是有很大风险的。 
风险在于控制样式表时的跨浏览器问题。首先,我尝试能不能通过jQuery插入一个带有class的"style"标签,但是却出现了跨浏览器问题。然后我尝试用javascript去创建stylesheet节点和class,但是实在有太多的API了,要搞清楚需要花不少的时间。最后,放弃了编程的方式,我在head区里写了一个带有class的style标签。通过编程的方式来创建stylesheet实在是太慢了,但是如果它一旦被创建好,那么给它一个ID和使用它的"disabled"属性就是轻而易举的事情了。

1  2  3   <style id="special_hide">.special_hide { display: none; }</style>  <!--  ...  -->  <div class="special_hide">Special hide DIV</div>
1   $('#special_hide').attr('disabled, 'true');
1   $('#special_hide').attr('disabled', 'false');

简要回顾一下,下面是改变元素显示状态的方法,按照最快到最慢的次序排列:

  • 禁用/启用样式表
  • .css('display', ''), .css('display', 'none')
  • .addClass(), .removeClass()
  • .show(), .hide()
  • .toggle()

.show() 和 .hide()

.toggle()

.addClass() 和 .removeClass()

.css({'display':'none'}) 和 .css({'display':'block'})

禁止样式表

然后在javascript里:

搞定!所有带有"special_hide"这个class的元素都显示出来了。要隐藏它们,你只需要……

现在它们全部都隐藏了。总的javascript耗时在所有浏览器上都是0-1ms。你的javascript只是用来改变一个属性。当然,浏览器还是需要花费时间去重新渲染页面的,但是实际上你已经避免了javascript的处理时间。如果你调用了.toggle(),.hide()或者.css()这几个方法,那么这个方法就会失效。因为那几个方法会通过内联方式设置css样式,这些样式有更高的优先级。要重新使这个方法生效,只需调用.css('display', '')把内联的样式移除掉。这个方法同样需要花费你更多的精力,因为那需要去定义class,同时把这些class赋给页面上需要进行显示/隐藏的元素,但是如果你所要处理的元素数量是极其庞大的话,那么这也许是值得的。

需要注意的是,在大多数的情况下,这些方法都足够的快了。当你要操作很大的jQuery集合时,那么.show() 和.hide()方法在IE下就会变得很慢了,这是你可能要用addClass() 或者 .removeClass()方法。禁用/启用样式表的方法只有在很极端的情况下才有必要用到

jquery的show/hide性能测试的更多相关文章

  1. jquery的show/hide/toggle详解

    通过阅读源码我们发现show,hide,toggle调用了showHide和isHidden这2个方法,所以我们要搞明白原理必须先看一下这2个方法. jQuery.fn.extend({ ...... ...

  2. hidden,display,visibility ,jQuery中的hide()区别

    hidden是html中的属性,规定元素是否可见 display是css中的样式,规定元素是否显示 visible 是css中的样式,规定元素是否可见 display:none ---不为被隐藏的对象 ...

  3. jQuery效果------隐藏hide()/显示show()

    hide()和show() hide():隐藏文本. show():显示文本. 语法: $(selector).hide(speed,callback); $(selector).show(speed ...

  4. JQuery 支持 hide 和 show 事件的方法与分析

    问题提出  JQuery不支持hide和show作为事件形式出现, 实际上这两个仅仅是JQuery对象的一个方法(fn): 有一类UI交互需求,根据一个DOM对象的或者显示对附属的DOM对象做相同操作 ...

  5. jQuery技巧大放送

    1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...

  6. 【前端性能】必须要掌握的原生JS实现JQuery

    很多时候,我们经常听见有人说jquery有多快多快.在这个各种类库满天飞的时候,不得不说的是,能有原生JS快吗? 是的,明显原生JS要更快,因为诸如JQuery这样的库必须要兼容各种浏览器和低版本和许 ...

  7. jQuery静态方法noConflict的使用和源码分析

    所谓静态方法是jQuery本身得公共方法,并不需要通过实例化来调用,一般也称为工具方法,下面先来列绝下jQuery.noConflict方法的用法: noConflict() 方法让渡变量 $ 的 j ...

  8. JQuery常用方法一览

    $(”p”).addClass(css中定义的样式类型); 给某个元素添加样式 $(”img”).attr({src:”test.jpg”,alt:”test Image”}); 给某个元素添加属性/ ...

  9. jquery实现前台倒计时。应用下单24小时后自动取消该订单

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

随机推荐

  1. js常用函数收集

    在js中,可以使用typeof获取变量或函数的类型,如下: <head runat="server"> <title></title> < ...

  2. rails中ActionController::InvalidAuthenticityToken解决办法

    Ror代码 class FooController < ApplicationController protect_from_forgery :except => :index # you ...

  3. quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  4. golang的序列与反序列化

    golang写backend之类的应用,还是挺方便的...使用encoding/json包时, 必须注意, 在struct定义的属性必须是exported, 否则不会设置值. 例如:type DRol ...

  5. mac中添加环境变量

    sudo vi /etc/paths 来编辑 paths,将环境变量添加到 paths 中. vim 是一个编辑器,另外还有几个,如:Pico,Emacs.  

  6. [转]ubuntu 下minicom超级终端的使用方法

    [转]ubuntu 下minicom超级终端的使用方法 http://blog.chinaunix.net/uid-25909619-id-3184639.html 系统环境: Ubuntu 11.0 ...

  7. 通过修改注册表来破解sqlyog

    Sqlyog作为一款可视化的数据库管理工具,各种方便我就不说了,但是未经汉化或者绿色过的软件存在30天的生命期,到期后我们就不可以使用了,要摸卸载重装,我们还可以去修改注册表,来延长它的生命期,具体步 ...

  8. Unity3D定制新建C#文件的头描述

    1. 修改模板内容如下: MAC:Unity.app/Contents/Resources/ScriptTemplates/81-C# Script-NewBehaviourScript.cs.txt ...

  9. 监听文本框输入开发仿新浪微博限制输入字数的textarea插件

    监听文本框输入 Firefox.Chrome.IE9,IE10 均支持 oninput 事件,此外所有版本的 IE 均支持 onpropertychange 事件. oninput 事件在用户输入.退 ...

  10. SQL Server性能优化(2)获取基本信息

    以下常用的SQL语句有利于我们分析数据库的基本信息,然后根据查询的结果进行优化. 1. 查看索引碎片     无论何时对基础数据执行插入.更新或删除操作,SQL Server 数据库引擎都会自动维护索 ...