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));
像任何其他on
或bind
-event处理程序一样使用它,除了可以将最后一个参数传递给另一个参数:
$(window).on('resize', function(e) { console.log(e.type + '-event was 200ms not triggered'); }, 200);
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有几个伟大的方法来完成这个任务: throttle
和debounce
。 即使你不使用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); } });