理解節流 & 防抖

概念

節流 (throttle)與 防抖 (debounce)都是爲了下降調用頻率的一種方式。html

相同點都是須要設置一個回調函數及週期時間,區別在於:react

  • 防抖是在中止觸發後的100ms,執行一次(在此時間段內,只要不中止觸發,理論上就永遠不會觸發回調)git

  • 節流是在不斷的觸發過程當中,每隔100ms就執行一次。github

下面簡單畫下流程圖瀏覽器

節流 throttle

在高頻觸發回調函數時,節流操做使回調函數在每隔一段時間按期執行一次,時間間隔內再觸發,不會從新執行。markdown

核心在於讓一個函數不要執行的太頻繁,減小一些過快的操做。less

相似於技能冷卻時間 ⏱ide

/** * 節流 * @param func * @param wait */
function throttle(func: Function, wait: number) {
  let timer: number = 0;
  return (...args) => {
    if (timer) { return }
    timer = window.setTimeout(() => {
      func(...args)
      timer = 0
    }, wait)
  }
}
複製代碼

防抖 debounce

在高頻觸發回調函數時,防抖操做使回調函數在必定時間間隔內,再次觸發會清空定時器,並從新計時;計時結束後輸出一次結果。函數

核心在於,在短期內大量觸發同一事件時,只會執行一次回調函數。避免把一次事件誤認爲屢次。oop

/** * 防抖 * @param func * @param wait */
function debounce(func: ()=>void, wait: number) {
  let timer: number = 0
  return (...args) => {
    clearTimeout(timer)
    timer = window.setTimeout(() => {
      func(...args)
      timer = 0; // 必須麼??
    }, wait)
  }
}
複製代碼

tips: 注意 args 剩餘參數的傳遞,不然執行回調函數時參數將丟失。

🌰 栗子

// 監聽頁面滾動條位置
const handleScrollTop = () => {
   const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滾動條位置:' + scrollTop);
}

// 防抖:在中止滾動100ms後,纔會輸出滾動條位置
window.onscroll = debounce(handleScrollTop,100)

// 節流:每隔100ms都會輸出一次滾動條位置
window.onscroll = throttle(showTop,100) 
複製代碼

常見場景

  • 監聽 scroll、mousemove 等事件 - 節流(每隔一秒計算一次位置)
  • 監聽瀏覽器窗口 resize 操做 - 防抖(只需計算一次)
  • 鍵盤文本輸入的驗證 - 防抖(連續輸入文字後發送請求進行驗證,驗證一次就好)
  • 提交表單 - 防抖(屢次點擊變爲一次)

節流、防抖有時用哪一個均可以,好比監聽頁面滾動,能夠節流(每一個一段時間出發一次回調),也能夠防抖(用戶當前此次滾動結束出發,繼續滾動等待下一次觸發)

React 中使用

  • Class 組件中

須要注意調用節流/防抖函數位置,在組件初始化時就綁定節流/防抖事件,不然回調函數不會被觸發。

constructor(props: any) {
  super(props);
  // 注意在此綁定!!
  this.handleScroll = throttle(this.handleScroll, 100)
}
複製代碼
  • 在函數式組件中,因爲渲染的問題使用起來須要特別注意。能夠參考

React hooks 怎樣作防抖?

阿里的useDebounce


參考

github.com/jashkenas/u…

github.com/lessfish/un…

linjingyi.cn/posts/7c266…

juejin.cn/post/685457…

相關文章
相關標籤/搜索