深入滾動(dòng)事件

簡(jiǎn)介

1 .使用到滾動(dòng)的場(chǎng)景

1 .懶加載
2 .loadmore
3 .affix.固定位置
4 .回到頂部

2 .HTML5標(biāo)準(zhǔn).scroll事件是每幀觸發(fā)一次

幀維度解析渲染過(guò)程

1 .瀏覽器渲染頁(yè)面的renderer進(jìn)程里面,涉及到兩個(gè)進(jìn)程.兩個(gè)進(jìn)程之間通過(guò)commit的消息保持同步
2 .Main進(jìn)程:瀏覽器渲染的主要執(zhí)行步驟.包含從js執(zhí)行到Composite合成的一系列操作
3 .Compositor線程:接收用戶的一些交互操作,比如滾動(dòng)->喚醒進(jìn)程進(jìn)行操作->接收Main線程的操作結(jié)果->commit給真正把頁(yè)面draw到屏幕上的GPU進(jìn)程


正常的操作

丟幀的操作

主線程里的操作太多,耗時(shí)長(zhǎng),commit的時(shí)間被推遲.瀏覽器來(lái)不及間頁(yè)面draw到屏幕上,就丟失了一幀
4 .Main線程完成最后之后,與Compositor線程使用commit進(jìn)行通信,Compositor調(diào)起Compositor來(lái)處理頁(yè)面
5 .頁(yè)面Paint結(jié)束之后,這一幀就結(jié)束了.GPU進(jìn)程里的GPU進(jìn)程負(fù)責(zé)把Render進(jìn)程操作好的頁(yè)面,交由GPU內(nèi)方法,由GPU把頁(yè)面draw到屏幕上
6 .屏幕刷新,我們就在瀏覽器上看到了新頁(yè)面

瀏覽器主要執(zhí)行步驟

1 .JavaScript:包含與視覺(jué)變化效果相關(guān)的js操作.包括不限于:Dom更新,元素樣式動(dòng)態(tài)改變
2.Style:樣式計(jì)算.瀏覽器根據(jù)css選擇器計(jì)算哪些元素應(yīng)該用哪些規(guī)則,然后間樣式規(guī)則落實(shí)到每個(gè)元素上面,確定每個(gè)元素具體的樣式
3 .Layout:布局.在知道每一個(gè)元素應(yīng)用哪些規(guī)則后,瀏覽器即可開(kāi)始計(jì)算他占據(jù)的空間大小以及在屏幕中的位置

1 .避免layout的操作,將DOM脫離文檔流在對(duì)其進(jìn)行操作,所有操作完畢之后再添加到文檔流中,這樣可以將重排以及重繪的次數(shù)降低到一次或兩次
2 .display:none
3 .DocumentFragment
4 .將原始元素拷貝到一個(gè)脫離文檔的節(jié)點(diǎn)中,修改這個(gè)副本,完成后替換掉原始元素

4 .Painting:繪制.繪制時(shí)填充像素的過(guò)程.涉及繪出文本,顏色,圖像,邊框和陰影.基本上包括元素的每個(gè)可視部分,繪制一般時(shí)在多個(gè)層上完成的.

1 .painting和draw的區(qū)別:paint是把內(nèi)容填充到頁(yè)面,而draw是把頁(yè)面反映到屏幕上

5 .Composite:合成.由于頁(yè)面的各部分可能被繪制到多層.因此他們還需要按照正確的順序繪制到屏幕上,以便正確渲染頁(yè)面.對(duì)于與另一個(gè)元素重疊的元素來(lái)說(shuō).這很重要,因?yàn)橐粋€(gè)錯(cuò)誤可能使另一個(gè)元素錯(cuò)誤的出現(xiàn)在另一個(gè)元素上面
6 .并不是每次都會(huì)走到全部的流程.
7 .重排:會(huì)走完整的流程,改變了元素的幾何屬性(寬度,高度,左側(cè)或者頂部位置等.必須檢查所有的其他元素).任何受印象的部分都需要重新繪制.而且最終繪制的元素需要重新合成,重排進(jìn)行了管道的每一步,性能受到很大的影響
8 .重繪:和上面相比不需要layout:如果是背景圖片,文字顏色或者陰影的話,不會(huì)影響頁(yè)面布局的屬性,瀏覽器會(huì)跳過(guò)布局
9 .不重排和重繪的情況:僅僅使用transform和opacity來(lái)實(shí)現(xiàn)動(dòng)畫(huà),會(huì)避免Layout和Paint操作
10 .每個(gè)層中對(duì)這個(gè)層進(jìn)行 Layout 或者 Paint 是不會(huì)影響其他層的智袭,一般會(huì)根據(jù)整個(gè)頁(yè)面的語(yǔ)義將頁(yè)面分為幾個(gè)層。
11 .查詢css屬性變化導(dǎo)致的操作https://csstriggers.com/

優(yōu)化操作

1 .避免在scroll事件中修改樣式屬性/將樣式操作從scroll事件中剝離
1 .變量的初始化,不依賴滾動(dòng)位置變化的計(jì)算都應(yīng)該在scroll事件外提前就緒

2 .使用web worker分離和頁(yè)面渲染無(wú)關(guān)的邏輯計(jì)算
3 .觸發(fā)監(jiān)聽(tīng)事件時(shí)使用函數(shù)節(jié)流或者去抖
4 .使用requestAnimationFrame提代定時(shí)器:瀏覽器每一次重回前觸發(fā)這個(gè)鉤子

1 .不要在 rAF 的回調(diào)函數(shù)中先修改樣式,再查詢樣式域帐,這樣就失去了 rAF 的作用睬隶〔宴郑可以將對(duì)樣式的查詢提前到回調(diào)函數(shù)中或者 rAF 中盡量靠前的位置
2 .動(dòng)畫(huà)是由瀏覽器按照一定的頻率一幀一幀的繪制的议纯,由css實(shí)現(xiàn)的動(dòng)畫(huà)的優(yōu)勢(shì)就是瀏覽器知道動(dòng)畫(huà)的開(kāi)始及每一幀的循環(huán)間隔崩溪,能夠在恰當(dāng)?shù)臅r(shí)間刷新UI浅役,給用戶一種流暢的體驗(yàn),而setInterval或setTimeout實(shí)現(xiàn)的JavaScript動(dòng)畫(huà)就沒(méi)有這么可靠了伶唯,因?yàn)闉g覽器壓根就無(wú)法保證每一幀渲染的時(shí)間間隔觉既,一般情況下,每秒平均刷新次數(shù)能夠達(dá)到60幀抵怎,就能夠給人流暢的體驗(yàn)奋救,即每過(guò) 1000/60 毫秒渲染新一幀即可,但從上面的例子知反惕,這一點(diǎn)單靠定時(shí)器是無(wú)法保證的。
為此演侯,requestAnimationFrame應(yīng)運(yùn)而生姿染,其作用就是讓瀏覽器流暢的執(zhí)行動(dòng)畫(huà)效果。可以將其理解為專(zhuān)門(mén)用來(lái)實(shí)現(xiàn)動(dòng)畫(huà)效果的api悬赏,通過(guò)這個(gè)api,可以告訴瀏覽器某個(gè)JavaScript代碼要執(zhí)行動(dòng)畫(huà)狡汉,瀏覽器收到通知后,則會(huì)運(yùn)行這些代碼的時(shí)候進(jìn)行優(yōu)化闽颇,實(shí)現(xiàn)流暢的效果盾戴,而不再需要開(kāi)發(fā)人員煩心刷新頻率的問(wèn)題了
3 .requestAnimationFrame接受一個(gè)動(dòng)畫(huà)執(zhí)行函數(shù)作為參數(shù),這個(gè)函數(shù)的作用是僅執(zhí)行一幀動(dòng)畫(huà)的渲染兵多,并根據(jù)條件判斷是否結(jié)束尖啡,如果動(dòng)畫(huà)沒(méi)有結(jié)束,則繼續(xù)調(diào)用requestAnimationFrame并將自身作為參數(shù)傳入剩膘。從示例來(lái)看衅斩,得到了效果平滑流暢的動(dòng)畫(huà),這樣就巧妙地避開(kāi)了每一幀動(dòng)畫(huà)渲染的時(shí)間間隔問(wèn)題
function animationWidth() {
  var div = document.getElementById('box');
  div.style.width = parseInt(div.style.width) + 1 + 'px';

  if(parseInt(div.style.width) < 200) {
    requestAnimationFrame(animationWidth)
  }
}
requestAnimationFrame(animationWidth);

5 .requestIdleCallback():會(huì)在瀏覽器的每一幀末尾觸發(fā).而且是空閑的時(shí)候,如果不空閑,就推遲到下一幀.適合于執(zhí)行在后臺(tái)運(yùn)行或者空閑時(shí)觸發(fā)回調(diào),否則推遲到下一幀.

避免強(qiáng)制重排:當(dāng)我們很頻繁的執(zhí)行下面這樣的特殊操作.就會(huì)打斷瀏覽器的節(jié)奏

1 .當(dāng)訪問(wèn)scrollWidth,clientWidth,offsetTop,computedStyle登屬性時(shí),會(huì)觸發(fā)這個(gè)效果,導(dǎo)致style和layout前移到j(luò)s代碼執(zhí)行過(guò)程中
2 .
elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight
elem.getClientRects(), elem.getBoundingClientRect()
elem.scrollWidth, elem.scrollHeight
elem.scrollLeft, elem.scrollTop
//這里不是求當(dāng)前div的滾動(dòng)距離的操作么,這個(gè)也會(huì)造成重排么?
以上的特殊讀操作,一定要使用requestAnimationFrame()包裹起來(lái).避免單個(gè)裸奔

提升合成層

1 .一些屬性會(huì)讓元素們創(chuàng)建出不同的渲染層

1 .relative,fixed,sticky,absolute
2 .有透明度的屬性
3 .css濾鏡
4 .css transform屬性

2 .達(dá)成一些條件,渲染條件會(huì)提升為合成層

1 .一鍵加速的iframe,iframe嵌入的頁(yè)面中有合成層
2 .3D或者硬件加速的2dCanvas
3 .video元素
4 .3d transform
5 .will-change:設(shè)置為opacity,transoorm,top,left,bottom,
6 .對(duì)opacity,tramsform,filter,backgroundFilter應(yīng)用了animation或者transition

3 .合成層之后,會(huì)交由GPU處理,比CPU處理快,但需要重繪的時(shí)候,只需要重繪自己的層,不會(huì)影響到其他的層

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怠褐,一起剝皮案震驚了整個(gè)濱河市畏梆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奈懒,老刑警劉巖奠涌,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異磷杏,居然都是意外死亡溜畅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)茴丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)达皿,“玉大人,你說(shuō)我怎么就攤上這事贿肩÷鸵” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵汰规,是天一觀的道長(zhǎng)汤功。 經(jīng)常有香客問(wèn)我,道長(zhǎng)溜哮,這世上最難降的妖魔是什么滔金? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮茂嗓,結(jié)果婚禮上餐茵,老公的妹妹穿的比我還像新娘。我一直安慰自己述吸,他們只是感情好忿族,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般道批。 火紅的嫁衣襯著肌膚如雪错英。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,713評(píng)論 1 312
  • 那天隆豹,我揣著相機(jī)與錄音椭岩,去河邊找鬼。 笑死璃赡,一個(gè)胖子當(dāng)著我的面吹牛判哥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鉴吹,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姨伟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了豆励?” 一聲冷哼從身側(cè)響起夺荒,我...
    開(kāi)封第一講書(shū)人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎良蒸,沒(méi)想到半個(gè)月后技扼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫩痰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年剿吻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片串纺。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丽旅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纺棺,到底是詐尸還是另有隱情榄笙,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布祷蝌,位于F島的核電站茅撞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏巨朦。R本人自食惡果不足惜米丘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糊啡。 院中可真熱鬧拄查,春花似錦、人聲如沸棚蓄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)癣疟。三九已至挣柬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間睛挚,已是汗流浹背邪蛔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扎狱,地道東北人侧到。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像淤击,于是被迫代替她去往敵國(guó)和親匠抗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容