背景 在lodash函數工具庫中,防抖_.debounce和節流_.throttle函數在一些頻繁觸發的事件中比較常用。 防抖函數_.debounce(func, [wait=0], [options=]) 創建一個 debounced(防抖動)函數,該函數會從上一次被調用後,延遲 wait 毫秒後 ...
背景
在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
的源碼。