vue專案使用lodash節流防抖函式問題與解決

前端cry發表於2023-10-08

背景

在lodash函式工具庫中,防抖_.debounce和節流_.throttle函式在一些頻繁觸發的事件中比較常用。

防抖函式_.debounce(func, [wait=0], [options=])

建立一個 debounced(防抖動)函式,該函式會從上一次被呼叫後,延遲 wait 毫秒後呼叫 func 方法。

引數

  • func (Function): 要防抖動的函式。
  • [wait=0] (number): 需要延遲的毫秒數。
  • [options=] (Object): 選項物件。
  • [options.leading=false] (boolean): 指定在延遲開始前呼叫。
  • [options.maxWait] (number): 設定 func 允許被延遲的最大值。
  • [options.trailing=true] (boolean): 指定在延遲結束後呼叫。

返回

  • (Function): 返回 debounced(防抖動)函式。

節流函式_.throttle(func, [wait=0], [options=])

建立一個節流函式,在 wait 毫秒內最多執行 func 一次的函式。

引數

  • func (Function): 要節流的函式。
  • [wait=0] (number): 需要節流的毫秒。
  • [options=] (Object): 選項物件。
  • [options.leading=true] (boolean): 指定呼叫在節流開始前。
  • [options.trailing=true] (boolean): 指定呼叫在節流結束後。

返回

(Function): 返回 throttled(節流)的函式。

在vue中使用防抖節流函式的問題

踩坑1

防抖節流函式實際上起到一個“稀釋”的作用,在vue專案中我們可能會這樣寫(節流為例)。

<template>
    <div>
        <button @click="add_throttle">加1</button>
        <h1>{{ number }}</h1>
    </div>
</template>

<script>
import { throttle } from 'lodash';
export default {
    data() {
        return {
            number: 1
        };
    },
    methods: {
        // add函式做節流處理
        add_throttle: throttle(this.add, 1000),
        add() {
            this.number++;
        }
    },
};
</script>

然後我們信心滿滿地F12開啟控制檯……

上面說add 這玩意兒 undefined了。

這其實是this的指向問題。實際上這裡的this並不是vue例項(至於是什麼,往下看你就知道了[doge]),所以自然不存在add()方法了。

踩坑2

既然直接使用this.add() 不成,那我們換個思路,把this.add()放在函式里呢?

methods: {
    // 做節流處理
    add_throttle: throttle(() => {
        this.add();
    }, 1000),
    add() {
        this.number++;
    }
}

然後,自信滿滿地再次開啟控制檯……

第一眼,誒,沒報錯,於是點選按鈕……

梅開二度……

其實還是this的指向問題。我們知道箭頭函式是沒有this的,所以這裡的this相當於踩坑1裡的this ,讓我們列印下,揭開它的廬山真面目。

methods: {
    // 做節流處理
    add_throttle: throttle(() => {
        console.log(this);
    }, 1000),
    add() {
        this.number++;
    }
}

好傢伙,原來這裡的this本身就是undefined

解決

既然是this的指向問題,那麼只要保證this指向vue例項就行了,箭頭函式換成宣告式函式。

methods: {
    // 做節流處理
    add_throttle: throttle(function () {
        this.add();
    }, 1000),
    add() {
        this.number++;
    }
}

結果很nice。

至於為什麼,大概是lodash的_.debounce函式對this做了一些處理(_.throttle函式本質還是呼叫了_.debounce函式),有興趣的小夥伴兒可以看看_.debounce的原始碼。

相關文章