防抖和節流嚴格算起來應該屬於效能優化的知識,實際上遇到的頻率也相當高,處理不當或者放任不管就容易引起瀏覽器卡死,所以還是很有必要早點掌握的。
這個按鈕只會在滾動到距離頂部一定位置之後才出現,那麼我們現在抽象出這個功能需求-- 監聽瀏覽器滾動事件,返回當前滾條與頂部的距離
這個需求很簡單,直接寫:
function showtop ()
window.onscroll = showtop
但是!
在執行的時候會發現存在乙個問題:這個函式的預設執行頻率,太!高!了!。 高到什麼程度呢?以chrome為例,我們可以點選選中乙個頁面的滾動條,然後點選一次鍵盤的【向下方向鍵】,會發現函式執行了8-9次!
然而實際上我們並不需要如此高頻的反饋,畢竟瀏覽器的效能是有限的,不應該浪費在這裡,所以接著討論如何優化這種場景。
基於上述場景,首先提出第一種思路:在第一次觸發事件時,不立即執行函式,而是給出乙個期限值比如200ms,然後:
效果:如果短時間內大量觸發同一事件,只會執行一次函式。
實現:既然前面都提到了計時,那實現的關鍵就在於settimeout
這個函式,由於還需要乙個變數來儲存計時,考慮維護全域性純淨,可以借助閉包來實現:
/*
* fn [function] 需要防抖的函式
* delay [number] 毫秒,防抖期限值
*/function debounce(fn,delay)else}}
當然 上述**是為了貼合思路,方便理解(這麼貼心不給個贊咩?),寫完會發現其實time = settimeout(fn,delay)
是一定會執行的,所以可以稍微簡化下:
/*****************************簡化後的分割線 ******************************/
function debounce(fn,delay)
timer = settimeout(fn,delay) // 簡化寫法
}}// 然後是舊**
function showtop ()
window.onscroll = debounce(showtop,1000) // 為了方便觀察效果我們取個大點的間斷值,實際使用根據需要來配置
此時會發現,必須在停止滾動1秒以後,才會列印出滾動條位置。
到這裡,已經把防抖實現了,現在給出定義:
繼續思考,使用上面的防抖方案來處理問題的結果是:
但是如果產品同學的期望處理方案是:即使使用者不斷拖動滾動條,也能在某個時間間隔之後給出反饋呢?
其實很簡單:我們可以設計一種類似控制閥門一樣定期開放的函式,也就是讓函式執行一次後,在某個時間段內暫時失效,過了這段時間後再重新啟用(類似於技能冷卻時間)。
效果:如果短時間內大量觸發同一事件,那麼在函式執行一次之後,該函式在指定的時間期限內不再工作,直至過了這段時間才重新生效。
function throttle(fn,delay)
// 工作時間,執行函式並且在間隔期內把狀態位設為無效
valid = false
settimeout(() => , delay)
}}/* 請注意,節流函式並不止上面這種實現方案,
例如可以完全不借助settimeout,可以把狀態位換成時間戳,然後利用時間戳差值是否大於指定間隔時間來做判定。
也可以直接將settimeout的返回的標記當做判斷條件-判斷當前定時器是否存在,如果存在表示還在冷卻,並且在執行fn之後消除定時器表示啟用,原理都一樣
*/// 以下照舊
function showtop ()
window.onscroll = throttle(showtop,1000)
執行以上**的結果是:
講完了這兩個技巧,下面介紹一下平時開發中常遇到的場景:
頁面resize事件,常見於需要做頁面適配的時候。需要根據最終呈現的頁面情況進行dom渲染(這種情形一般是使用防抖,因為只需要判斷最後一次的變化情況)
防抖與節流方案 函式防抖和節流
在前端開發的過程中,我們經常會需要繫結一些持續觸發的事件,如 resize scroll mousemove 等等,但有些時候我們並不希望在事件持續觸發的過程中那麼頻繁地去執行函式。通常這種情況下我們怎麼去解決的呢?一般來講,防抖和節流是比較好的解決方案。讓我們先來看看在事件持續觸發的過程中頻繁執行...
函式防抖和節流
在前端開發的過程中,我們經常會需要繫結一些持續觸發的事件,如 resize scroll mousemove 等等,但有些時候我們並不希望在事件持續觸發的過程中那麼頻繁地去執行函式。通常這種情況下我們怎麼去解決的呢?一般來講,防抖和節流是比較好的解決方案。讓我們先來看看在事件持續觸發的過程中頻繁執行...
函式防抖和節流
在前端開發的過程中,我們經常會需要繫結一些持續觸發的事件,如 resize scroll mousemove 等等,但有些時候我們並不希望在事件持續觸發的過程中那麼頻繁地去執行函式。通常這種情況下我們怎麼去解決的呢?一般來講,防抖和節流是比較好的解決方案。讓我們先來看看在事件持續觸發的過程中頻繁執行...