因為它,我差點刪庫跑路:js防抖與節流
- 2021 年 7 月 14 日
- 筆記
前言
前端踩雷:短時間內重複提交導致數據重複。
對於前端大佬來說,防抖和節流的技術應用都是基本操作。對於「兼職」前端開發的來說,這些都是需要躺平的坑。
我們今天就來盤一盤js防抖與節流,並且解決開發中遇到的問題。
PS:重複提交問題我用的是防抖的方法進行避免。
防抖的概念
防抖又叫為函數防抖(debounce):指觸發事件後,在 n 秒內函數只能執行一次,如果觸發事件後在 n 秒內又觸發了事件,則會重新計算函數延執行時間。
前端開發中,常見的事件如,onresize,scroll,mousemove ,mousehover 等會短時間內多次觸發(頻繁觸發),不做限制的話可能一秒執行幾百次,
在這些函數內部如果還執行了其他函數,尤其是執行了操作 DOM 的函數的話(瀏覽器操作 DOM 是很耗費性能的),那不僅會浪費電腦資源,
還會降低程式運行速度,甚至造成瀏覽器卡死、崩潰。
除此之外,短時間內重複調用 ajax 不僅會造成數據關係的混亂,還會造成網路擁堵,增加伺服器壓力等問題。
防抖程式碼實現
防抖的關鍵是需要一個 setTimeout 來輔助實現,延遲運行需要執行的程式碼。
如果方法多次觸發,則把上次記錄的延遲執行程式碼用 clearTimeout 清掉,重新開始計時。
若計時期間事件沒有被重新觸發,等延遲時間計時完畢,則執行目標程式碼。
注意:當你一直連續不斷的點擊超過你設置的時間,並且只有第一次點擊有效,這不是bug,這是概念問題,注意看下面標紅這部分,
防抖又叫為函數防抖(debounce):指觸發事件後,在 n 秒內函數只能執行一次,如果觸發事件後在 n 秒內又觸發了事件,則會重新計算函數延執行時間。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js防抖與節流</title> </head> <body> <!--按鈕--> <button id="btn">點擊提交</button> <script type="text/javascript"> var num = 1; const seckill = () => { console.log('我是防抖,你點擊了按鈕' + num++) } // 防抖函數 const debounce = (fun, wait) => { let timeout; return function () { if (timeout) { clearTimeout(timeout); } //第一次執行任務,timeout是null,此時callNow是true,需要立即執行 let callNow = !timeout; timeout = setTimeout(() => { timeout = null; }, wait); if (callNow) { fun.apply(this); } } }; //點擊提交按鈕 let btn = document.getElementById('btn'); //調用方法( 1s內只允許一次操作) btn.addEventListener('click', debounce(seckill, 1000)); </script> </body> </html>
節流的概念
節流又叫函數節流(throttle):指當持續觸發事件時,保證一定時間段內只調用一次事件處理函數。
節流程式碼實現
- 滑鼠連續不斷地觸發某事件(如點擊),只在單位時間內只觸發一次;
- 在頁面的無限載入場景下,需要用戶在滾動頁面時,每隔一段時間發一次 ajax 請求,而不是在用戶停下滾動頁面操作時才去請求數據;
- 監聽滾動事件,比如是否滑到底部自動載入更多,用throttle來判斷;
節流和防抖都是差不多的,區別在於是「立即執行版」 和 「非立即執行版」
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js防抖與節流</title> </head> <body> <!--按鈕--> <button id="btn">點擊提交</button> <script type="text/javascript"> var num = 1; const seckill = () => { console.log('點擊了按鈕' + num++) } function throttle(callback, delay) { var timer, begin = new Date(); return function () { //記錄事件觸發時的時間 var current = new Date(); //清除上一次定時器任務 clearTimeout(timer); //判斷距上一次觸發是否已過了delay的時間 if (current - begin >= delay) { callback(); begin = current; } else { timer = setTimeout(() => { callback(); }, delay); } } } //點擊提交按鈕 let btn = document.getElementById('btn'); //調用方法( 1s內只允許一次操作) btn.addEventListener('click', throttle(seckill, 1000)); </script> </body> </html>
防抖和節流的區別
函數防抖:是n秒內只執行一次,如果觸發事件後在 n 秒內又觸發了事件,則會重新計算函數延執行時間。
函數節流:是間隔時間執行,不管事件觸發有多頻繁,都會保證在規定時間內一定會執行一次真正的事件處理函數。
原理:
防抖是維護一個計時器,規定在delay時間後觸發函數,但是在delay時間內再次觸發的話,都會清除當前的 timer 然後重新設置超時調用,即重新計時。這樣一來,只有最後一次操作能被觸發。
節流是通過判斷是否到達一定時間來觸發函數,若沒到規定時間則使用計時器延後,而下一次事件則會重新設定計時器。
總結
函數防抖和節流的實現很簡單,能很友好的解決前端開發過程中的遇到的很多問題,提升性能,優化用戶體驗。
在實際的開發中,防抖函數還是節流函數的選擇需要開發者針對不同的應用場景進行相應的應用。
歡迎關注訂閱微信公眾號【熊澤有話說】,更多好玩易學知識等你來取
作者:熊澤-學習中的苦與樂 公眾號:熊澤有話說 出處://www.cnblogs.com/xiongze520/p/15011323.html 創作不易,任何人或團體、機構全部轉載或者部分轉載、摘錄,請在文章明顯位置註明作者和原文鏈接。
|