我使用JQuery这样:

$(window).resize(function() { ... });

但是,如果用户通过拖动窗口边缘来手动调整浏览器窗口的大小,上面的.resize事件会触发多次。

问题:如何在浏览器窗口调整大小完成后调用函数(使事件只触发一次)?


当前回答

许多解决方案。我尝试在mouuseevent之后执行事件,所以我在ouse进入窗口后添加了重载:

jQuery(window).resize(function() {
        // this. is window
        if(  this.resizeTO) {
            clearTimeout(this.resizeTO) 
        };
    
         this.resizeTO = setTimeout(function() {
            
                jQuery(window).mouseenter(function() {
                    if( jQuery(window).width() < 700 &&   jQuery(window).width() > 400 ){
                        console.log("mouseenter  reloads elements"); 
                        // is loading the page  
                        location.reload();
                        //
                     }; // just mobile
                }); // mouse  fired    
        }, 400);  // set Time Ouuut
}); 



 

其他回答

我使用以下函数来延迟重复操作,它将适用于您的情况:

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

用法:

$(window).resize(function() {
    delay(function(){
      alert('Resize...');
      //...
    }, 500);
});

传递给它的回调函数,只会在指定的时间量之后执行最后一次调用延迟,否则计时器将被重置,我发现这对于其他目的很有用,如检测用户何时停止输入等…

非常感谢大卫沃尔什,这里是一个香草版本的下划线debounce。

代码:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

简单的用法:

var myEfficientFn = debounce(function() {
    // All the taxing stuff you do
}, 250);

$(window).on('resize', myEfficientFn);

裁判:http://davidwalsh.name/javascript-debounce-function

声明全局延迟侦听器:

var resize_timeout;

$(window).on('resize orientationchange', function(){
    clearTimeout(resize_timeout);

    resize_timeout = setTimeout(function(){
        $(window).trigger('resized');
    }, 250);
});

下面使用监听器来调整事件大小:

$(window).on('resized', function(){
    console.log('resized');
});

以下是CMS解决方案的修改,可以在代码中的多个地方调用:

var waitForFinalEvent = (function () {
  var timers = {};
  return function (callback, ms, uniqueId) {
    if (!uniqueId) {
      uniqueId = "Don't call this twice without a uniqueId";
    }
    if (timers[uniqueId]) {
      clearTimeout (timers[uniqueId]);
    }
    timers[uniqueId] = setTimeout(callback, ms);
  };
})();

用法:

$(window).resize(function () {
    waitForFinalEvent(function(){
      alert('Resize...');
      //...
    }, 500, "some unique string");
});

CMS的解决方案是很好的,如果你只调用它一次,但如果你调用它多次,例如,如果你的代码的不同部分设置了单独的回调窗口调整大小,那么它将失败b/c他们共享计时器变量。

通过这种修改,您可以为每个回调提供一个惟一的id,这些惟一id用于将所有超时事件分开。

前面提到的一些解决方案对我不起作用,尽管它们的用途更广泛。或者,我发现了这一个,在窗口大小调整的工作:

$(window).bind('resize', function(e){
    window.resizeEvt;
    $(window).resize(function(){
        clearTimeout(window.resizeEvt);
        window.resizeEvt = setTimeout(function(){
        //code to do after window is resized
        }, 250);
    });
});