1. 程式人生 > 其它 >防抖和節流(React和Vue版)

防抖和節流(React和Vue版)

技術標籤:js

背景

在公司專案中有購物車功能,最近在測試中碰到一個問題,在點選購物車某個商品的新增或者減少按鈕時,每次的點選後都會請求伺服器,如果快速點選按鈕將會對伺服器造成大量的請求,這顯然會佔用大量的伺服器資源。而防抖和節流是控制事件觸發頻率的方法,可以對此類事件進行很好的限制。

防抖

函式防抖,這裡的抖動就是執行的意思,而一般的抖動都是持續的,多次的。假設函式持續多次執行,我們希望讓它冷靜下來再執行。也就是當持續觸發事件的時候,函式是完全不執行的,等最後一次觸發結束的一段時間之後,再去執行。在我的業務場景裡面就是,一段時間內不管你點選了多少次按鈕,只執行最後一次的點選事件。

React

debounce = (method, delay) => {
        //設定一個檢驗setTimeout是否在執行的引數,預設未執行
        let {timer = null} = this.state;
        //將當前的this賦值給that
        //否則在下面函式作用域中this是當前函式作用域,沒有setState方法
        let that = this;
        return function (...args) {
            //檢驗是否有正在執行的定時器方法,如果有,就把上一個定時器廢棄
            if
(timer) clearTimeout(timer); //生成一個新的定時器方法重新計數 timer = setTimeout(function () { method.apply(this, args); }, delay); that.setState({timer}); }; };

然後在下面的點選事件中使用這個函式:

let cart = this.debounce(this.cart, 1000);
cart(
carts, index, index2);

在這裡插入圖片描述
可以看到商品數量一直變化,只有最後一次點選事件後才執行了請求伺服器的方法。

Vue

function debounce(func,delay){

  var timer = null;
  
  return function (...args) {
    var that = this;

    //如果timer為真,就把上次的timeout銷燬,然後執行最近一次的setTimeout
    if (timer) clearTimeout(timer);
    
    timer = setTimeout(() => {
      func.apply(that, args);
    }, delay);
  };
}

再點選事件中呼叫這個函式:

 debounceClick: debounce(function () {
        console.log(9999);
      }, 5000)

節流

節流的意思是讓函式有節制地執行,而不是毫無節制的觸發一次就執行一次。什麼叫有節制呢?就是在事件觸發後,會先執行一次事件函式,執行之後如果在規定時間間隔內再觸發事件,將不出觸發函式,超過規定的事件間隔後會再次觸發一次,如此往復。

React

 throttle = (fn, delay = 3000) => {
        //期間間隔執行 節流
        let {canRun} = this.state;
        let that = this;
        // console.log(111, canRun);
        return (...rest) => {
            if (!canRun) return;
            canRun = false;
            // console.log(222, canRun);
            setTimeout(() => {
                fn.apply(this, rest);
                canRun = true;
                that.setState({canRun});
            }, delay);
            that.setState({canRun});
        };
    };

呼叫和防抖一樣:

let cart = this.throttle(this.cart, 2000);
cart(carts, index, index2);

在這裡插入圖片描述
可以看到在點選的時候執行了兩次,這就是防抖和節流的區別,防抖只會執行最後一次的點選事件,而節流是在一段時間內之執行一次。

Vue

export function throttle(fn, wait) {
  let canRun = true; // 通過閉包儲存一個標記
  return function () {
    if (!canRun) return; // 在函式開頭判斷標記是否為true,不為true則return
    canRun = false; // 立即設定為false
    setTimeout(() => { // 將外部傳入的函式的執行放在setTimeout中
      fn.apply(this, arguments);
      // 最後在setTimeout執行完畢後再把標記設定為true(關鍵)表示可以執行下一次迴圈了。當定時器沒有執行的時候標記永遠是false,在開頭被return掉
      canRun = true;
    }, wait);
  };
}

呼叫和防抖一樣:

throttleClick: throttle(function () {
        console.log(9999);
      }, 1000)