最近因為疫情隔離居家辦公,閑着沒事也在回憶和整合學過的知識,這里給大家分享幾個有關“防抖”和“節流”方法,希望對大家有所幫助
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 小結
- 函數防抖和函數節流都是防止某一時間內頻繁觸發。
- 函數防抖是在指定時間只執行一次,而函數節流是每到指定間隔時間執行一次。
- 函數防抖是將幾次操作合並為一此操作進行,函數節流使得一定時間內只觸發一次函數。
應用場景
- 防抖debounce
search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源。
window觸發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其只觸發一次
- 節流throttle
鼠標不斷點擊觸發,mousedown(單位時間內只觸發一次)
監聽滾動事件,比如是否滑到底部自動加載更多,用來判斷。
如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。