JQuery:只有在完成调整大小后才能调用RESIZE事件?

浏览器窗口完成大小调整后,如何调用函数?

我试图这样做,但有问题。 我正在使用JQuery Resize事件函数:

$(window).resize(function() { ... // how to call only once the browser has FINISHED resizing? }); 

但是,如果用户手动调整浏览器窗口的大小,则会连续调用此函数。 也就是说,在短时间内可能会调用这个函数几十次。

我怎样才能一次调用调整大小功能(一旦浏览器窗口完成调整大小)?

UPDATE

也无需使用全局变量。

这是一个使用jh指令的例子

您可以将引用ID存储到任何setInterval或setTimeout。 喜欢这个:

 var loop = setInterval(func, 30); // some time later clear the interval clearInterval(loop); 

去抖 。

 function debouncer( func , timeout ) { var timeoutID , timeout = timeout || 200; return function () { var scope = this , args = arguments; clearTimeout( timeoutID ); timeoutID = setTimeout( function () { func.apply( scope , Array.prototype.slice.call( args ) ); } , timeout ); } } $( window ).resize( debouncer( function ( e ) { // do stuff } ) ); 

注意,你可以使用这个方法来去除任何东西(关键事件等)。

调整超时参数以获得最佳的预期效果。

您可以将setTimeout()clearTimeout()jQuery.data结合使用:

 $(window).resize(function() { clearTimeout($.data(this, 'resizeTimer')); $.data(this, 'resizeTimer', setTimeout(function() { //do something alert("Haven't resized in 200ms!"); }, 200)); }); 

更新

我写了一个扩展,以增强jQuery on (& bind )-event处理程序on的默认值。 如果事件在给定时间间隔内未触发,则将一个或多个事件的事件处理函数附加到所选元素。 如果您只想在延迟后触发回调(如调整大小事件),则此功能非常有用。 https://github.com/yckart/jquery.unevent.js

 ;(function ($) { var methods = { on: $.fn.on, bind: $.fn.bind }; $.each(methods, function(k){ $.fn[k] = function () { var args = [].slice.call(arguments), delay = args.pop(), fn = args.pop(), timer; args.push(function () { var self = this, arg = arguments; clearTimeout(timer); timer = setTimeout(function(){ fn.apply(self, [].slice.call(arg)); }, delay); }); return methods[k].apply(this, isNaN(delay) ? arguments : args); }; }); }(jQuery)); 

像任何其他onbind -event处理程序一样使用它,除了可以将最后一个参数传递给另一个参数:

 $(window).on('resize', function(e) { console.log(e.type + '-event was 200ms not triggered'); }, 200); 

http://jsfiddle.net/ARTsinn/EqqHx/

 var lightbox_resize = false; $(window).resize(function() { console.log(true); if (lightbox_resize) clearTimeout(lightbox_resize); lightbox_resize = setTimeout(function() { console.log('resize'); }, 500); }); 

只是为了增加上面的内容,通常会因为滚动条出现而出现不必要的调整大小事件,下面是一些代码以避免这种情况:

 function registerResize(f) { $(window).resize(function() { clearTimeout(this.resizeTimeout); this.resizeTimeout = setTimeout(function() { var oldOverflow = document.body.style.overflow; document.body.style.overflow = "hidden"; var currHeight = $(window).height(), currWidth = $(window).width(); document.body.style.overflow = oldOverflow; var prevUndefined = (typeof this.prevHeight === 'undefined' || typeof this.prevWidth === 'undefined'); if (prevUndefined || this.prevHeight !== currHeight || this.prevWidth !== currWidth) { //console.log('Window size ' + (prevUndefined ? '' : this.prevHeight + "," + this.prevWidth) + " -> " + currHeight + "," + currWidth); this.prevHeight = currHeight; this.prevWidth = currWidth; f(currHeight, currWidth); } }, 200); }); $(window).resize(); // initialize } registerResize(function(height, width) { // this will be called only once per resize regardless of scrollbars changes }); 

见jsfiddle

Underscore.js有几个伟大的方法来完成这个任务: throttledebounce 。 即使你不使用Underscore,也要看看这些函数的来源。 这是一个例子:

 var redraw = function() {'redraw logic here'}; var debouncedRedraw = _.debounce(redraw, 750); $(window).on('resize', debouncedRedraw); 

这是我的做法:

 document.addEventListener('DOMContentLoaded', function(){ var tos = {}; var idi = 0; var fn = function(id) { var len = Object.keys(tos).length; if(len == 0) return; to = tos[id]; delete tos[id]; if(len-1 == 0) console.log('Resize finished trigger'); }; window.addEventListener('resize', function(){ idi++; var id = 'id-'+idi; tos[id] = window.setTimeout(function(){fn(id)}, 500); }); }); 

resize事件侦听器捕获所有传入的resize调用,为每个调用创建一个超时函数,并将超时标识符与由'id-' (可用作数组键)作为前缀的迭代数字一起保存在tos数组中。

每次timout触发器都调用fn function,检查是否是tos数组中的最后一个超时(fn函数删除每个执行的timout)。 如果为真(= if(len-1 == 0) ),则调整大小结束。

jQuery提供了一个删除事件处理程序的方法

 $(window).resize(function(){ if(magic == true) { $(window).off('resize', arguments.callee); } });