天天看點

Web前端性能優化——高頻觸發事件的防抖

JS 提供了行為層的支援,為使用者提供了互動的操作性。然而,部分事件卻經常有意無意的被頻繁觸發,比如浏覽器視窗的 resize 事件,某個元素的 mouseover 事件,如果處理觸發事件的回調函數過重,那麼最後的結果就是浏覽器死掉。

為此,如何提供一種對此類事件的高頻觸發的防抖是相當重要的。

所謂的防抖,就是在一定時間内,規定事件被觸發的最多次數。

參考:http://www.gbtags.com/gb/share/1217.htm

給出下面的防抖程式

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);
    };
}
           

若添加 mouseover 事件,并規定隻運作它每300毫秒執行一次,則

var link = document.getElementById("links");

link.addEventListener("mouseover", debounce(function(){
	//添加回調處理函數的函數體
},300,true), false);
           

但是,經測試發現,若把時間設定大些,比如5秒,那麼每次moueover 事件的發生都會重新整理計時器,也就是說如果使用者一直在mouseover,則這個處理事件永遠不會發生。

為此,我們可以加多一個條件:

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;
        if(!timeout){
	    clearTimeout(timeout);
	    timeout = setTimeout(later, wait);
	}
        if(callNow) func.apply(context, args);
    };
}
           

這樣一來實作的效果就是,當使用者的 mouseover 觸發了事件發生,就會觸發計時器的計時,過程中其他的 mouseover 事件不會觸發事件發生,也不會觸發計時器的重置,效果才是真正的在規定時間内隻允許事件被觸發一次。

繼續閱讀