前端必會的“防抖”和“節流”方法


最近因為疫情隔離居家辦公,閑着沒事也在回憶和整合學過的知識,這里給大家分享幾個有關“防抖”和“節流”方法,希望對大家有所幫助

1 前言

在前端開發過程中,會遇到很多實時輸入查詢、滾動條觸發等業務。而這些頻發操作的事件,如果每次觸發都進行執行的話,會造成性能下降、后台的壓力變大,那么此時就需要使用防抖和節流進行處理。

防抖和節流,見名思義:防抖是防止抖動,節流是節約流量。

2 防抖

防抖(Debounce) 指的是觸發事件后n秒后才能執行函數,如果在n秒內觸發了事件,則會重新計算執行時間。

常見場景:點擊按鈕、拍照、下拉觸底加載下一頁等。

持續觸發輸入事件時,並不會立即執行func函數,而是在指定時間delay中沒有再次觸發事件時,才會進行延時執行func函數。

2.1 原始栗子(未進行防抖處理)

為了更加深入透徹地理解為什么要進行防抖處理,我們可以先體驗不進行防抖的輸入函數觸發ajax實時請求的情況。

<div class="box">
  沒有進行防抖處理的:<input type="text" id="name" name="name">
</div>
<script>
  // 模仿一段ajax請求
  function ajax(value){
    console.log("ajax request: " + value + ", time: " + new Date());
  }

  const inputBox = document.getElementById("name");
  inputBox.addEventListener("keyup",e=>{
    ajax(e.target.value);
  })
</script>

復制代碼

運行結果:

上面結果所示,只要我們在輸入框中每次輸入值、按下鍵盤,那么就會觸發一次ajax請求,這對於用戶和開發者而言都是不好的體驗和資源的浪費。此時,我們想到每次用戶輸入文字都是需要一定時間的,那么我們可以定義在規定時間進行完整輸入才能進行請求,這樣我們可以減輕對后台的壓力。

2.2 防抖栗子

前面,我們看到對於短時間內頻繁點擊或輸入的事件觸發,未使用防抖處理的事件對於用戶體驗並不是很好。因此我們可以使用防抖進行處理,如下:

<div class="box">
  進行防抖處理的:<input type="text" id="name" name="name">
</div>
<script>
  // 模仿一段ajax請求
  function ajax(value){
    console.log("ajax request: " + value + ", time: " + new Date());
  }

  // 防抖函數
  function debounce(func,delay){
    let timeout; //定時器
    return function(arguments){
      // 判斷定時器是否存在,存在的話進行清除,重新進行定時器計數
      if(timeout) clearTimeout(timeout);//清除之前的事件
      timeout = setTimeout(()=>{
        func.call(this,arguments);//執行事件
      },delay);
    }
  }

  const inputBox = document.getElementById("name");
  // 使用防抖函數進行封裝ajax
  let debounceAjax = debounce(ajax,500);
  inputBox.addEventListener("keyup",e=>{
    debounceAjax(e.target.value);
  })
</script>

復制代碼

運行結果: 

 

從上面的運行結果可以看出,在500ms內輸入文字按下鍵盤都不會觸發請求事件,而是在輸入框的定時器500ms停止輸入后發送請求。實現原理很簡單,就是對於頻繁輸入的輸入框請求事件添加定時器進行計數,在指定時間內進行頻繁輸入並不會進行ajax請求,而是在指定時間間隔內停止輸入才會執行函數。當停止輸入但在此定時器計數時間內,會重新進行觸發請求事件

3 節流

節流(Throttle) 指的是連續觸發事件但是在n秒中只執行一次函數。即不管你在指定時間內觸發多少次函數,但是它只執行一次事件。(只有一次生效)

常見場景:即時查詢

在持續進行觸發輸入事件時,並不會立即執行func的函數請求,而是每隔指定的delay時間后才會執行一次func函數,不管這段時間內你點擊了多少次。

3.1 節流栗子

<div class="box">
  進行節流處理的:<input type="text" id="name" name="name">
</div>
<script>
  // 模仿一段ajax請求
  function ajax(value){
    console.log("ajax request: " + value + ", time: " + new Date());
  }

  // 節流--定時器版
  function throttle(func,delay){
    let timeout;//定義一個定時器標記
    return function(arguments){
      // 判斷是否存在定時器
      if(!timeout){ 
        // 創建一個定時器
        timeout = setTimeout(()=>{
          // delay時間間隔清空定時器
          clearTimeout(timeout);
          func.call(this,arguments);
        },delay)
      }
    }
  }

  const inputBox = document.getElementById("name");
  // 使用節流函數進行封裝ajax
  let throttleAjax = throttle(ajax,500);
  inputBox.addEventListener("keyup",e=>{
    throttleAjax(e.target.value);
  })
</script>

復制代碼

運行結果: 

 

 

從上面可以看到,無論我們在輸入框輸入多少文字,在指定時間內只執行一次函數

4 小結

  1. 函數防抖和函數節流都是防止某一時間內頻繁觸發。
  2. 函數防抖是在指定時間只執行一次,而函數節流是每到指定間隔時間執行一次。
  1. 函數防抖是將幾次操作合並為一此操作進行,函數節流使得一定時間內只觸發一次函數。

應用場景

  1. 防抖debounce

search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源。

window觸發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其只觸發一次

  1. 節流throttle

鼠標不斷點擊觸發,mousedown(單位時間內只觸發一次)

監聽滾動事件,比如是否滑到底部自動加載更多,用來判斷。

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM