防抖(debounce)節流(throttle)

1、防抖

1.原理瀏覽器

事件頻繁觸發的狀況下,只有觸發的間隔超過指定間隔時,任務纔會執行。bash

(大白話就是,你儘管觸發事件,可是我必定在事件觸發 n 秒後才執行,若是你在一個事件觸發的 n 秒內又觸發了這個事件,那我就以新的事件的時間爲準,n 秒後才執行)閉包

export const Debounce = (func, wait) => {
    var wait = wait || 200;
    var timeout;

    return function () {
        /*
          1.將this指向正確的對象。
          使用debounce函數時,打印this會指向Window對象,
          因此用context綁定上下文
        */
        var context = this;
        
        /*
          2.arguments:將不肯定的變量替換到函數中了。
            Eg:在test()方法中,因爲咱們不肯定變量有多少,好比
            test("古天樂", "太陽才能黑的男人"),
            又或者 test("渣渣輝", [1, 2, 3], 10),
            這時候只須要在函數 test 中用 arguments 接收就好了。
        */
        var args = arguments;
        
        // 三、每次當用戶點擊/輸入的時候,把前一個定時器清除
        clearTimeout(timeout)
        
        // 四、建立一個新的 setTimeout,
              這樣能保證點擊按鈕後的timeout間隔內若是用戶還點擊了的話,
              就不會執行 fn 函數
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}
複製代碼
// 防抖的應用。
methods:{
    onClick:Debounce(function(){
        ...
    }, 1000)
}
複製代碼

還有一種場景,點擊事件後馬上執行,等到中止觸發 n 秒後,才能夠從新觸發執行。app

export const Debounce = (func, wait, immediate) = {

    var timeout;

    return function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 若是已經執行過,再也不執行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}
複製代碼

當即執行的使用場景:函數

  • window 的 resize、scroll
  • input的雙向綁定,即輸完以後等外n毫秒時間後才賦值
  • 鼠標移入移出...

2、節流

  • 1.原理

持續觸發事件,每隔一段時間,只執行一次事件。ui

關於節流的實現,有兩種實現方式,一種是使用時間戳,一種是設置定時器。this

  • 2.時間戳節流
/*
    當觸發事件的時候,咱們取出當前的時間戳,
    而後減去以前的時間戳(最一開始值設爲 0 ),
    若是大於設置的時間週期,就執行函數,而後更新時間戳爲當前的時間戳,
    若是小於,就不執行。
*/
export const throttle = (func, wait) => {
    var context, args;
    var previous = 0;

    return function() {
        var now = +new Date();
        context = this;
        args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}
複製代碼
// 節流的應用。
methods:{
    onClick:Debounce(function(){
        ...
    }, 1000)
}
複製代碼
  • 3.定時器節流
/*
    當觸發事件的時候,咱們設置一個定時器,
    再觸發事件的時候,若是定時器存在,就不執行,
    直到定時器執行,而後執行函數,
    清空定時器,這樣就能夠設置下個定時器。
*/
function throttle(func, wait) {
    // 一、經過閉包保存一個標記
    var timeout;

    return function() {
        context = this;
        args = arguments;
        // 二、在函數開頭判判定時器是否存在,存在則中斷函數
        if (!timeout) {
        
            timeout = setTimeout(function(){
                //三、執行完事件(好比調用完接口)以後,從新將這個標誌設置爲null
                timeout = null;
                func.apply(context, args)
            }, wait)
            
        }
    }
}
複製代碼

節流的應用場景spa

- 懶加載要監聽計算滾動條的位置,使用節流按必定時間的頻率獲取
- 用戶點擊提交按鈕,假設咱們知道接口大體的返回時間的狀況下,
  咱們使用節流,只容許必定時間內點擊一次。
複製代碼

防抖和節流減小瀏覽器沒必要要損耗的緣由

主要涉及到瀏覽器渲染頁面的機制雙向綁定

// 具體信息本身額外補充吧
- 瀏覽器解析 URL
- 重繪與迴流複製代碼
相關文章
相關標籤/搜索