jquery的show/hide性能测试

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


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

  • .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()
java

.toggle()
编程

.addClass() 和 .removeClass()
浏览器

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

禁止样式表
dom

而后在javascript里:ide

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

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

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

相关文章
相关标签/搜索