談談js防抖和節流
阿新 • • 發佈:2020-09-03
常見的防抖節流應用場景:監聽滾動條、輸入框的驗證、echarts自適應處理
如果事件處理沒有頻率限制,就會加重瀏覽器的負擔,影響使用者的體驗感,因此,我們可以採取防抖(debounce)和節流(throttle)來處理,減少呼叫事件的頻率,達到較好的使用者體驗
防抖
當事件被觸發時,設定一個定時器,若期間又被觸發,則重新設定週期,直到週期結束
//需求:監聽瀏覽器滾動事件,返回當前滾條與頂部的距離 //需求實現(未處理版) function watchScroll() { let scrollTop = document.body.scrollTop || document.documentElement.scrollTop console.log(scrollTop) } window.onscroll = watchScroll //需求實現(debounce處理版) //如果不做處理,在拖動滾動條時這個函式觸發的頻率會很高,為了不浪費瀏覽器效能,這裡可以用上防抖函式 /** * @param fn:需要防抖處理的函式,delay:防抖設定的間隔 * @return function */ function debounce(fn, delay) { let timer = null //這裡用到了閉包,每次onscroll觸發都會呼叫下一行返回的匿名函式,所以timer=null只會執行一次,並且timer會一直保留到閉包函式銷燬為止 return function () { if (timer) { clearTimeout(timer) timer = setTimeout(fn, delay) } else { timer = setTimeout(fn, delay) } } } function showTop () { let scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log(scrollTop); } window.onscroll = debounce(showTop,1000) //經過處理,滾動條停止滾動1秒以後,才會打印出滾動條位置
節流
當事件被觸發時,在一定時間內只有第一次觸發有效,若期間又被觸發則無效,直到週期結束
//試試把上述防抖方案用節流來處理 /** * @param fn:需要節流處理的函式,delay:節流設定的間隔 * @return function */ function throttle(fn, delay) { let working = false return function () { if (working) { return false //如果已經設定了定時器且未執行,則不會再次執行到下幾行設定定時器的程式碼 } working = true //將狀態設定為'執行中' setTimeout(function () { fn() working = false //定時器內函式執行完畢後將狀態設定為'未執行' }, delay) } } function showTop () { let scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log(scrollTop); } window.onscroll = throttle(showTop,1000) //上述節流寫法用的是閥門思想,也可以用時間戳來寫,把狀態換成時間戳,然後利用時間戳差值是否大於指定間隔時間來做判定 //經過處理,只有在一直拖著滾動條進行滾動的情況下,會以1s的時間間隔輸出當前位置和頂部的距離,個人認為監聽滾動條這種情景還是用防抖處理比較恰當
因為demo很簡單,無需考慮作用域和引數傳遞,所以上述防抖節流案例沒有用到apply,實際上肯定還要考慮傳遞argument以及上下文環境(this指向)
apply用法 https://blog.csdn.net/qq_21397815/article/details/90482341