如果浏览器窗口已完成调整大小,如何调用函数?
我试图这样做,但我遇到了问题。我正在使用JQuery Resize事件函数:
$(window).resize(function() {
... // how to call only once the browser has FINISHED resizing?
});
但是,如果用户手动调整浏览器窗口的大小,则此功能将连续称为 。这意味着它可能会在很短的时间间隔内调用此函数几十次。
如何只调用一次(一旦浏览器窗口调整完成后)调整resize函数?
更新
也无需使用全局变量。
答案 0 :(得分:128)
Here is an example using thejh's instructions
您可以将引用ID存储到任何setInterval或setTimeout。像这样:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
答案 1 :(得分:85)
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
} ) );
注意,您可以将此方法用于您要去抖的任何内容(关键事件等)。
调整超时参数以获得最佳效果。
答案 2 :(得分:21)
您可以将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
(&amp; bind
) - 事件处理程序。如果在给定间隔内未触发事件,它会将一个或多个事件的事件处理函数附加到所选元素。如果您只想在延迟之后(例如resize事件)触发回调,则此功能非常有用。
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
- 事件处理程序一样使用它,除了您可以将额外参数作为最后一个传递:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
答案 3 :(得分:7)
var lightbox_resize = false;
$(window).resize(function() {
console.log(true);
if (lightbox_resize)
clearTimeout(lightbox_resize);
lightbox_resize = setTimeout(function() {
console.log('resize');
}, 500);
});
答案 4 :(得分:7)
只是为了补充上面的内容,由于滚动条弹出和滚出,通常会产生不需要的调整大小事件,这里有一些代码可以避免这种情况:
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
答案 5 :(得分:5)
Underscore.js为此任务提供了几种很棒的方法:throttle
和debounce
。即使您没有使用下划线,也请查看这些功能的来源。这是一个例子:
var redraw = function() {'redraw logic here'};
var debouncedRedraw = _.debounce(redraw, 750);
$(window).on('resize', debouncedRedraw);
答案 6 :(得分:2)
这是我的方法:
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-event-listener捕获所有传入的resize调用,为每个调用创建一个timeout-function并保存timeout-identifier以及'id-'
前面的迭代数(可用作数组键) tos
- 阵列
每次,timout触发,它调用fn
- 函数,检查,如果那是tos
数组中的最后一次超时(fn-function删除每个执行的timout)。如果为true(= if(len-1 == 0)
),则调整大小结束。
答案 7 :(得分:1)
jQuery提供了一个off
方法来删除事件处理程序
$(window).resize(function(){
if(magic == true) {
$(window).off('resize', arguments.callee);
}
});