爲何不用rAF進行滾動節流

前言

以前寫了一篇長列表實現的分享 -- 「前端長列表」開源庫解析及最佳實踐html

而後面試被問到的最多的問題就是:有沒有作節流前端

當時的回答是沒有,可是又說不出一個系統的回答web

本文就來講說爲何長列表不須要作節流,以及什麼狀況下滾動須要作節流面試

背景知識之事件循環

詳見HTML規範api

這裏只挑與本文相關的講併發

在事件循環中定義了不少任務源,好比鼠標鍵盤等輸入操做的用戶交互任務源app

一次點擊操做,其實包含多個輸入操做(mousedown,mouseup,click),都添加到相同的任務源隊列中,進而產生多輪的事件循環,其表現就是執行相關元素的事件回調(宏任務)webapp

宏任務執行後,後面就是微任務隊列和更新渲染階段oop

每輪事件循環多是很是快的,每秒執行事件循環的次數可能大於60次post

受硬件刷新率影響,咱們只要保證 fps 達到最大硬件刷新率(好比60)便可,所以不須要每輪事件循環都更新渲染

輸入事件與滾動事件的執行時機

對於輸入事件,其執行時機爲每輪事件循環的任務執行階段,這個事件是不受刷新率影響的,每秒的執行次數可能多於60次

爲何談這個呢,由於這個與滾動事件(scroll)回調的執行時機不一致

按照 HTML 規範,滾動事件回調在 UI Render 階段的某個步驟中進行,而不是單獨的一個任務源

也就是說,滾動事件回調受渲染時機影響,僅執行更新渲染時才執行該回調。

換句話說,該事件自帶節流。

舉個例子驗證下輸入事件和更新渲染的執行時機

document.addEventListener("mousemove",function(){
  let start = performance.now()
  console.log("mousemove:",start)
  requestAnimationFrame(function(t){console.log("ui render:",start,t)})
})
// 結果就是可能輸出幾輪 mousemove 而後執行一次 ui render -- 清空 rAF 回調隊列(輸出屢次 ui render)
/* mousemove: 4091.025000088848 ui render: 4091.025000088848 4077.594 mousemove: 4098.845000029542 ui render: 4098.845000029542 4094.278 mousemove: 4110.160000040196 mousemove: 4115.5349999899045 ui render: 4110.160000040196 4110.962 ui render: 4115.5349999899045 4110.962 mousemove: 4123.810000019148 mousemove: 4130.160000058822 ui render: 4123.810000019148 4127.719 ui render: 4130.160000058822 4127.719 */
複製代碼

說明更新渲染有必定的間隔,至少是 1/60 的間隔,而輸入任務沒有此限制

因此,如下代碼是沒有效果的,由於該回調已經自帶節流了

document.addEventListener("scroll",function(e){
  requestAnimationFrame(function(t){
    //執行scroll具體邏輯
  })
})
複製代碼

何時滾動須要作節流

利用節流能夠減小回調的執行次數,使得固定時間週期內只執行一次

剛纔提到,滾動事件自帶節流,節流的時間週期是與渲染時機相關

判斷是否須要額外的節流的關鍵是:當前的節流規則,是否大部分回調的執行都能讓用戶受益

若是是動畫效果,實時繪製的界面等,則不須要額外的節流了。

以長列表爲例,每次執行滾動回調,會計算新的渲染列表項及滾動偏移位置。若是應用更大時間週期的節流,會出現某一幀出現滾動但界面沒有更新的狀況,讓用戶感受產生卡頓。

而其餘比較複雜的業務邏輯,不能在短期內獲得反饋的,則須要額外進行節流

以滾動懶加載圖片爲例

因爲每秒的滾動回調的執行次數可能達到60次,而每次執行都須要去獲取當前處於視區的佔位圖併發起圖片請求

而這大部分回調的執行,用戶是不能受益的,因此咱們能夠提升節流的時間週期,好比 500ms 這樣

結論

滾動事件已自帶節流,只有一些特定的業務邏輯才須要額外進行更高時間週期的節流

拓展閱讀

  1. scroll events: requestAnimationFrame VS requestIdleCallback VS passive event listeners
相關文章
相關標籤/搜索