背景
在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
的原始碼。