前端處理防抖和節流


防抖(debounce):當持續觸發事件時,保證只執行最后一次事件處理函數

在給DOM綁定事件時,有些事件我們是無法控制觸發頻率的。
 如鼠標移動事件onmousemove, 滾動滾動條事件onscroll,
窗口大小改變事件onresize,瞬間的操作都會導致這些事件會被高頻觸發。
 如果事件的回調函數較為復雜,就會導致響應跟不上觸發,出現頁面卡頓,假死現象。 
在實時檢查輸入時,如果我們綁定onkeyup事件發請求去服務端檢查,用戶輸入過程中,事件的觸發頻率也會很高,
會導致大量的請求發出,響應速度會大大跟不上觸發。

如何實現防抖呢?

我們拿滾動事件舉例子,用戶的滾動會頻繁觸發滾動事件,很容易造成頁面卡死。那么我們可以封裝如下一個函數。

每次想調用函數的時候,設置一個定時器讓函數延遲執行。

當連續觸發的時候,前面每次定時器都會清除掉,都會停掉前面的定時器所以函數並不會運行,只會執行最后一次。

 

// 防抖

function debounce(fn) {
    let timeout = null; // 創建一個標記用來存放定時器的返回值
    return function () {
        clearTimeout(timeout); // 每當用戶輸入的時候把前一個 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又創建一個新的 setTimeout, 這樣就能保證輸入字符后的 interval 間隔內如果還有字符輸入的話,就不會執行 fn 函數
            fn()
        }, 500);
    };
}
function sayHi() {
    console.log('防抖成功');
}
let box = document.getElementById('box')
box.addEventListener('click', debounce(sayHi))

節流(throttle)::當持續觸發事件時,保證一定時間段內只調用一次事件處理函數

如何實現節流?
當用戶連續操作的時候,我們設置一個定時器,一段時間后執行函數,並且執行完把標記改為true,所以在函數沒有執行完之前一直是false,

可能有的同學認為連續操作那么函數連續運行,那么canRun這個標記不一直是true嗎,

並不是,注意這里是一個閉包結構,真正每次調用的其實是throttle里面return的函數並不是每次都調用throttle,所以canRun只是提供初始值,並不會每次都重新賦值為true。

所以用戶連續操作的時候,比如用戶一秒鍾連續操作了十次,但是對於我們這個代碼來說,只可能每500毫秒執行一次,因為只有500ms之后canRun才為true,才能開啟下一個定時器。

所以哪怕用戶一秒鍾之內連續點了十次,其實也只是能執行兩次。這就符合節流的本意。

function throttle(fn) {
    let canRun = true; // 通過閉包保存一個標記
    return function () {
        if (!canRun) return; // 在函數開頭判斷標記是否為true,不為true則return
        canRun = false; // 立即設置為false
        setTimeout(() => { // 將外部傳入的函數的執行放在setTimeout中
            fn()
            // 最后在setTimeout執行完畢后再把標記設置為true(關鍵)表示可以執行下一次循環了。當定時器沒有執行的時候標記永遠是false,在開頭被return掉
            canRun = true;
        }, 500);
    };
}
function sayHi(e) {
    console.log('節流');
}
window.addEventListener('resize', throttle(sayHi));

總結:防抖動和節流本質是不一樣的。

防抖動是將多次執行變為最后一次執行,節流是將多次執行變成每隔一段時間執行。

 

文章轉載至https://blog.csdn.net/qq_40096030/article/details/114372174

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM