1. 程式人生 > >在React、Vue和小程式中使用函式節流和函式防抖

在React、Vue和小程式中使用函式節流和函式防抖

在上一篇中我總結了節流函式和防抖函式的基本原理:總結前端函式防抖與函式節流
接下來介紹一下防抖函式和節流函式在前端框架中的使用。

在使用前一定要注意兩個問題:

  • 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。