优化jQuery调整屏幕和滚动性能

在最近的一个jQuery插件中,我使用到了jQuery中的resize()方法来检测用户调整浏览器窗口并运行相关代码。

我注意到resize window时各个浏览器的性能消耗不一。

IE、Safari、Chrome在调整窗口变化中一直在执行resize事件

Opera则在这个过程中发生了很多次resize事件,但在结束调整时执行。

Firefox则是只在调整结束后才执行事件。

而我们想要的明显是在结束调整之后才执行事件。幸运的是我们可以通过以下几种方法来调整。

调整运行时间

  1. 创建一个在你发生调整时需要执行的任意代码的函数。
  2. 使用resize()方法,你可以运行函数并给它设置一个超过时间执行,从而达到在某一段时间内执行一次函数。

代码如下:

(function($) {
    var resizeTimer; // Set resizeTimer to empty so it resets on page load
    function resizeFunction() {
        // Stuff that should happen on resize
    };
    // On resize, run the function and reset the timeout
    // 250 is the delay in milliseconds. Change as you see fit.
    $(window).resize(function() {
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(resizeFunction, 250);
    });
    resizeFunction();
})(jQuery);

jQuery惰性插件

jQuery throttle / debounce: Sometimes, less is more!

(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);

使用方法:

function log( event ) {
  console.log( $(window).scrollTop(), event.timeStamp );
};

// Console logging happens on window scroll, WAAAY more often
// than you want it to.
$(window).scroll( log );

// Console logging happens on window scroll, but no more than
// once every 250ms.
$(window).scroll( $.throttle( 250, log ) );

// Note that in jQuery 1.4+ you can unbind by reference using
// either the throttled function, or the original function.
$(window).unbind( 'scroll', log );

其他js代码

(function($,sr){

// debouncing function from John Hann
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
var debounce = function (func, threshold, execAsap) {
var timeout;

return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};

if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);

timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };

})(jQuery,'smartresize');
// usage:
$(window).smartresize(function(){
// code that takes it easy...
});

总结起来第一种简单容易理解,第二种则是比较全面,代码也少,第三种也差不多。

参考资料

第一种:http://gomakethings.com/javascript-resize-performance/

第二种:http://benalman.com/projects/jquery-throttle-debounce-plugin/

第三种:http://www.paulirish.com/2009/throttled-smartresize-jquery-event-handler/

JavaScript代码:http://unscriptable.com/2009/03/20/debouncing-javascript-methods/

以后对于滚动、调整窗体大小等最好使用这种方法来减少JavaScript执行的次数。慎记。

关于jQuery优化的问题欢迎点击:jQuery性能优化大全


关注我

我的微信公众号:前端开发博客,在后台回复以下关键字可以获取资源。

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF
  • 回复「Vue脑图」获取 Vue 相关脑图
  • 回复「思维图」获取 JavaScript 相关思维图
  • 回复「简历」获取简历制作建议
  • 回复「简历模板」获取精选的简历模板
  • 回复「加群」进入500人前端精英群
  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。
  • 回复「知识点」下载高清JavaScript知识点图谱

每日分享有用的前端开发知识,加我微信:caibaojian89 交流