在React、Vue和小程式中使用函式節流和函式防抖
阿新 • • 發佈:2019-01-23
在上一篇中我總結了節流函式和防抖函式的基本原理:總結前端函式防抖與函式節流。
接下來介紹一下防抖函式和節流函式在前端框架中的使用。
在使用前一定要注意兩個問題:
- this的指向
- 事件物件的傳遞
React中使用防抖函式和節流函式
在React事件呼叫時,React傳遞給事件處理程式是一個合成事件物件的例項。SyntheticEvent
物件是通過合併得到的。 這意味著在事件回撥被呼叫後,SyntheticEvent 物件將被重用並且所有屬性都將被取消
。 這是出於效能原因。 因此,您無法以非同步方式訪問該事件
。
React合成事件官方文件
//React無法非同步訪問事件物件
function onClick (event) {
console.log(event); // => nullified object.
console.log(event.type); // => "click"
const eventType = event.type; // => "click"
setTimeout(function() {
console.log(event.type); // => null
console.log(eventType); // => "click"
}, 0);
// 不能工作。 this.state.click 事件只包含空值。
this.setState({clickEvent: event});
// 您仍然可以匯出事件屬性。
this.setState({eventType: event.type});
}
所以在用防抖或節流函式封裝時,非同步方式訪問事件物件出現問題。解決的方法如下:
- 方法一:呼叫合成事件物件的persist()方法
- 方法二:深拷貝事件物件
function debounce(func, wait=500) {
let timeout; // 定時器變數
return function(event){
clearTimeout(timeout); // 每次觸發時先清除上一次的定時器,然後重新計時
event.persist && event.persist() //保留對事件的引用
//const event = e && {...e} //深拷貝事件物件
timeout = setTimeout(()=>{
func(event)
}, wait); // 指定 xx ms 後觸發真正想進行的操作 handler
};
}
class Test extends React.Component{
handleChange = debounce((e)=>{
console.log(e.type)
console.log(this)
})
render(){
return (
<div>
<input type="text" onChange={this.handleChange}/>
</div>
)
}
}
在Vue中使用防抖函式和節流函式
<div id="app">
<input type="text" @keydown="handleChange">
</div>
<script>
function debounce(func, wait=500) {
let timeout; // 定時器變數
return function(event) {
clearTimeout(timeout); // 每次觸發時先清除上一次的定時器,然後重新計時
timeout = setTimeout(()=>{
console.log(123,this)
func.call(this,event)
}, wait); // 指定 xx ms 後觸發真正想進行的操作 handler
};
}
new Vue({
el: '#app',
methods: {
handleChange:debounce(function(e){
console.log(e)
console.log(this)
})
}
})
</script>
在小程式中使用防抖函式和節流函式
<input bindinput='change' style='border:1px solid #000;'></input>
function debounce(func, wait = 500) {
let timeout;
return function (event) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.call(this, event)
}, wait);
};
}
Page({
change: debounce(function(e){
console.log(e)
console.log(this)
})
})
總結
上面this的指向涉及了複雜的知識點:箭頭函式、閉包、class方法的this、事件呼叫、call等。單個理解這些知識點並不是很難,但是組合在一起後,理解就很困難了。目前自己對上面框架中防抖函式的this指向還不清楚,自己只是在程式碼中試錯來理解this。