成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

DOM操作成本到底高在哪兒?

yuxue / 1372人閱讀

摘要:刨根問(wèn)底,這里說(shuō)的成本,到底高在哪兒呢什么是文檔對(duì)象模型什么是可能很多人第一反應(yīng)就是等標(biāo)簽至少我是,但要知道,是,是,對(duì)象模型,是為提供的。操作具體的成本,說(shuō)到底是造成瀏覽器回流和重繪,從而消耗資源。

從我接觸前端到現(xiàn)在,一直聽到的一句話:操作DOM的成本很高,不要輕易去操作DOM。尤其是React、vue等MV*框架的出現(xiàn),數(shù)據(jù)驅(qū)動(dòng)視圖的模式越發(fā)深入人心,jQuery時(shí)代提供的強(qiáng)大便利地操作DOM的API在前端工程里用的越來(lái)越少。刨根問(wèn)底,這里說(shuō)的成本,到底高在哪兒呢?
什么是DOM
Document Object Model 文檔對(duì)象模型

什么是DOM?可能很多人第一反應(yīng)就是div、p、span等html標(biāo)簽(至少我是),但要知道,DOM是Model,是Object Model,對(duì)象模型,是為HTML(and XML)提供的API。HTML(Hyper Text Markup Language)是一種標(biāo)記語(yǔ)言,HTML在DOM的模型標(biāo)準(zhǔn)中被視為對(duì)象,DOM只提供編程接口,卻無(wú)法實(shí)際操作HTML里面的內(nèi)容。但在瀏覽器端,前端們可以用腳本語(yǔ)言(JavaScript)通過(guò)DOM去操作HTML內(nèi)容。

那么問(wèn)題來(lái)了,只有JavaScript才能調(diào)用DOM這個(gè)API嗎?

答案是NO

Python也可以訪問(wèn)DOM。所以DOM不是提供給Javascript的API,也不是Javascript里的API。

PS: 實(shí)質(zhì)上還存在CSSOM:CSS Object Model,瀏覽器將CSS代碼解析成樹形的數(shù)據(jù)結(jié)構(gòu),與DOM是兩個(gè)獨(dú)立的數(shù)據(jù)結(jié)構(gòu)

瀏覽器渲染過(guò)程
討論DOM操作成本,肯定要先了解該成本的來(lái)源,那么就離不開瀏覽器渲染。

這里暫只討論瀏覽器拿到HTML之后開始解析、渲染。(怎么拿到HTML資源的可能后續(xù)另開篇總結(jié)吧,什么握握握手啊揮揮揮揮手啊,萬(wàn)惡的flag...)

解析HTML,構(gòu)建DOM樹(這里遇到外鏈,此時(shí)會(huì)發(fā)起請(qǐng)求)

解析CSS,生成CSS規(guī)則樹

合并DOM樹和CSS規(guī)則,生成render樹

布局render樹(Layout/reflow),負(fù)責(zé)各元素尺寸、位置的計(jì)算

繪制render樹(paint),繪制頁(yè)面像素信息

瀏覽器會(huì)將各層的信息發(fā)送給GPU,GPU將各層合成(composite),顯示在屏幕上

1.構(gòu)建DOM樹

  
    
    
    Critical Path
  
  
    

Hello web performance students!

無(wú)論是DOM還是CSSOM,都是要經(jīng)過(guò)Bytes → characters → tokens → nodes → object model這個(gè)過(guò)程。

DOM樹構(gòu)建過(guò)程:當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn)都構(gòu)建好后才會(huì)去構(gòu)建當(dāng)前節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)。
2.構(gòu)建CSSOM樹

上述也提到了CSSOM的構(gòu)建過(guò)程,也是樹的結(jié)構(gòu),在最終計(jì)算各個(gè)節(jié)點(diǎn)的樣式時(shí),瀏覽器都會(huì)先從該節(jié)點(diǎn)的普遍屬性(比如body里設(shè)置的全局樣式)開始,再去應(yīng)用該節(jié)點(diǎn)的具體屬性。還有要注意的是,每個(gè)瀏覽器都有自己默認(rèn)的樣式表,因此很多時(shí)候這棵CSSOM樹只是對(duì)這張默認(rèn)樣式表的部分替換。

3.生成render樹
DOM樹和CSSOM樹合并生成render樹

簡(jiǎn)單描述這個(gè)過(guò)程:

DOM樹從根節(jié)點(diǎn)開始遍歷可見節(jié)點(diǎn),這里之所以強(qiáng)調(diào)了“可見”,是因?yàn)槿绻龅皆O(shè)置了類似display: none;的不可見節(jié)點(diǎn),在render過(guò)程中是會(huì)被跳過(guò)的(但visibility: hidden; opacity: 0這種仍舊占據(jù)空間的節(jié)點(diǎn)不會(huì)被跳過(guò)render),保存各個(gè)節(jié)點(diǎn)的樣式信息及其余節(jié)點(diǎn)的從屬關(guān)系。

4.Layout 布局

有了各個(gè)節(jié)點(diǎn)的樣式信息和屬性,但不知道各個(gè)節(jié)點(diǎn)的確切位置和大小,所以要通過(guò)布局將樣式信息和屬性轉(zhuǎn)換為實(shí)際可視窗口的相對(duì)大小和位置。

5.Paint 繪制

萬(wàn)事俱備,最后只要將確定好位置大小的各節(jié)點(diǎn),通過(guò)GPU渲染到屏幕的實(shí)際像素。

Tips

在上述渲染過(guò)程中,前3點(diǎn)可能要多次執(zhí)行,比如js腳本去操作dom、更改css樣式時(shí),瀏覽器又要重新構(gòu)建DOM、CSSOM樹,重新render,重新layout、paint;

Layout在Paint之前,因此每次Layout重新布局(reflow 回流)后都要重新出發(fā)Paint渲染,這時(shí)又要去消耗GPU;

Paint不一定會(huì)觸發(fā)Layout,比如改個(gè)顏色改個(gè)背景;(repaint 重繪)

圖片下載完也會(huì)重新出發(fā)Layout和Paint;

何時(shí)觸發(fā)reflow和repaint
reflow(回流): 根據(jù)Render Tree布局(幾何屬性),意味著元素的內(nèi)容、結(jié)構(gòu)、位置或尺寸發(fā)生了變化,需要重新計(jì)算樣式和渲染樹;
repaint(重繪): 意味著元素發(fā)生的改變只影響了節(jié)點(diǎn)的一些樣式(背景色,邊框顏色,文字顏色等),只需要應(yīng)用新樣式繪制這個(gè)元素就可以了;
reflow回流的成本開銷要高于repaint重繪,一個(gè)節(jié)點(diǎn)的回流往往回導(dǎo)致子節(jié)點(diǎn)以及同級(jí)節(jié)點(diǎn)的回流;

GoogleChromeLabs 里面有一個(gè)csstriggers,列出了各個(gè)CSS屬性對(duì)瀏覽器執(zhí)行Layout、Paint、Composite的影響。

引起reflow回流
現(xiàn)代瀏覽器會(huì)對(duì)回流做優(yōu)化,它會(huì)等到足夠數(shù)量的變化發(fā)生,再做一次批處理回流。

頁(yè)面第一次渲染(初始化)

DOM樹變化(如:增刪節(jié)點(diǎn))

Render樹變化(如:padding改變)

瀏覽器窗口resize

獲取元素的某些屬性:
瀏覽器為了獲得正確的值也會(huì)提前觸發(fā)回流,這樣就使得瀏覽器的優(yōu)化失效了,這些屬性包括offsetLeft、offsetTop、offsetWidth、offsetHeight、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、調(diào)用了getComputedStyle()或者IE的currentStyle

引起repaint重繪

reflow回流必定引起repaint重繪,重繪可以多帶帶觸發(fā)

背景色、顏色、字體改變(注意:字體大小發(fā)生變化時(shí),會(huì)觸發(fā)回流)

優(yōu)化reflow、repaint觸發(fā)次數(shù)

避免逐個(gè)修改節(jié)點(diǎn)樣式,盡量一次性修改

使用DocumentFragment將需要多次修改的DOM元素緩存,最后一次性append到真實(shí)DOM中渲染

可以將需要多次修改的DOM元素設(shè)置display: none,操作完再顯示。(因?yàn)殡[藏元素不在render樹內(nèi),因此修改隱藏元素不會(huì)觸發(fā)回流重繪)

避免多次讀取某些屬性(見上)

將復(fù)雜的節(jié)點(diǎn)元素脫離文檔流,降低回流成本

為什么一再?gòu)?qiáng)調(diào)將css放在頭部,將js文件放在尾部 DOMContentLoaded 和 load

DOMContentLoaded 事件觸發(fā)時(shí),僅當(dāng)DOM加載完成,不包括樣式表,圖片...

load 事件觸發(fā)時(shí),頁(yè)面上所有的DOM,樣式表,腳本,圖片都已加載完成

CSS 資源阻塞渲染

構(gòu)建Render樹需要DOM和CSSOM,所以HTML和CSS都會(huì)阻塞渲染。所以需要讓CSS盡早加載(如:放在頭部),以縮短首次渲染的時(shí)間。

JS 資源

阻塞瀏覽器的解析,也就是說(shuō)發(fā)現(xiàn)一個(gè)外鏈腳本時(shí),需等待腳本下載完成并執(zhí)行后才會(huì)繼續(xù)解析HTML

這和之前文章提到的瀏覽器線程有關(guān),瀏覽器中js引擎線程和渲染線程是互斥的,詳見《從setTimeout-setInterval看JS線程》

普通的腳本會(huì)阻塞瀏覽器解析,加上defer或async屬性,腳本就變成異步,可等到解析完畢再執(zhí)行

async異步執(zhí)行,異步下載完畢后就會(huì)執(zhí)行,不確保執(zhí)行順序,一定在onload前,但不確定在DOMContentLoaded事件的前后

defer延遲執(zhí)行,相對(duì)于放在body最后(理論上在DOMContentLoaded事件前)

舉個(gè)栗子

  
    
    
  
  
    

Hello web performance students!

瀏覽器拿到HTML后,從上到下順序解析文檔

此時(shí)遇到css、js外鏈,則同時(shí)發(fā)起請(qǐng)求

開始構(gòu)建DOM樹

這里要特別注意,由于有CSS資源,CSSOM還未構(gòu)建前,會(huì)阻塞js(如果有的話)

無(wú)論JavaScript是內(nèi)聯(lián)還是外鏈,只要瀏覽器遇到 script 標(biāo)記,喚醒JavaScript解析器,就會(huì)進(jìn)行暫停 blocked 瀏覽器解析HTML,并等到 CSSOM 構(gòu)建完畢,才執(zhí)行js腳本

渲染首屏(DOMContentLoaded 觸發(fā),其實(shí)不一定是首屏,可能在js腳本執(zhí)行前DOM樹和CSSOM已經(jīng)構(gòu)建完render樹,已經(jīng)paint)

首屏優(yōu)化Tips
說(shuō)了這么多,其實(shí)可以總結(jié)幾點(diǎn)瀏覽器首屏渲染優(yōu)化的方向

減少資源請(qǐng)求數(shù)量(內(nèi)聯(lián)亦或是延遲動(dòng)態(tài)加載)

使CSS樣式表盡早加載,減少@import的使用,因?yàn)樾枰馕鐾陿邮奖碇兴衖mport的資源才會(huì)算CSS資源下載完

異步j(luò)s:阻塞解析器的 JavaScript 會(huì)強(qiáng)制瀏覽器等待 CSSOM 并暫停 DOM 的構(gòu)建,導(dǎo)致首次渲染的時(shí)間延遲

so on...

知道操作DOM成本多高了嗎?
其實(shí)寫了這么多,感覺偏題了,大量的資料參考的是chrome開發(fā)者文檔。感覺js腳本資源那塊還是有點(diǎn)亂,包括和DOMContentLoaded的關(guān)系,希望大家能多多指點(diǎn),多多批評(píng),謝謝大佬們。

操作DOM具體的成本,說(shuō)到底是造成瀏覽器回流reflow和重繪reflow,從而消耗GPU資源。

參考文獻(xiàn):

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/

已同步至個(gè)人博客-軟硬皆施
Github 歡迎star :)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/93802.html

相關(guān)文章

  • DOM操作成本到底高在哪兒?

    摘要:刨根問(wèn)底,這里說(shuō)的成本,到底高在哪兒呢什么是文檔對(duì)象模型什么是可能很多人第一反應(yīng)就是等標(biāo)簽至少我是,但要知道,是,是,對(duì)象模型,是為提供的。操作具體的成本,說(shuō)到底是造成瀏覽器回流和重繪,從而消耗資源。 從我接觸前端到現(xiàn)在,一直聽到的一句話:操作DOM的成本很高,不要輕易去操作DOM。尤其是React、vue等MV*框架的出現(xiàn),數(shù)據(jù)驅(qū)動(dòng)視圖的模式越發(fā)深入人心,jQuery時(shí)代提供的強(qiáng)大便...

    MASAILA 評(píng)論0 收藏0
  • 回流、重繪及其優(yōu)化

    摘要:回流重繪及其優(yōu)化渲染過(guò)程渲染引擎通過(guò)通過(guò)網(wǎng)絡(luò)請(qǐng)求接收渲染內(nèi)容解析抽象抽象出布局繪畫抽象渲染引擎的第一步是解析文檔并將解析的元素轉(zhuǎn)換為樹中的實(shí)際節(jié)點(diǎn)。 回流、重繪及其優(yōu)化 渲染過(guò)程 渲染引擎通過(guò)通過(guò)網(wǎng)絡(luò)請(qǐng)求接收渲染內(nèi)容 解析HTML抽象DOM tree 抽象出Render tree 布局(layout)render tree 繪畫render tree 抽象DOM tree 渲染引擎...

    Clect 評(píng)論0 收藏0
  • 回流、重繪及其優(yōu)化

    摘要:回流重繪及其優(yōu)化渲染過(guò)程渲染引擎通過(guò)通過(guò)網(wǎng)絡(luò)請(qǐng)求接收渲染內(nèi)容解析抽象抽象出布局繪畫抽象渲染引擎的第一步是解析文檔并將解析的元素轉(zhuǎn)換為樹中的實(shí)際節(jié)點(diǎn)。 回流、重繪及其優(yōu)化 渲染過(guò)程 渲染引擎通過(guò)通過(guò)網(wǎng)絡(luò)請(qǐng)求接收渲染內(nèi)容 解析HTML抽象DOM tree 抽象出Render tree 布局(layout)render tree 繪畫render tree 抽象DOM tree 渲染引擎...

    Sike 評(píng)論0 收藏0
  • 回流、重繪及其優(yōu)化

    摘要:回流重繪及其優(yōu)化渲染過(guò)程渲染引擎通過(guò)通過(guò)網(wǎng)絡(luò)請(qǐng)求接收渲染內(nèi)容解析抽象抽象出布局繪畫抽象渲染引擎的第一步是解析文檔并將解析的元素轉(zhuǎn)換為樹中的實(shí)際節(jié)點(diǎn)。 回流、重繪及其優(yōu)化 渲染過(guò)程 渲染引擎通過(guò)通過(guò)網(wǎng)絡(luò)請(qǐng)求接收渲染內(nèi)容 解析HTML抽象DOM tree 抽象出Render tree 布局(layout)render tree 繪畫render tree 抽象DOM tree 渲染引擎...

    alaege 評(píng)論0 收藏0
  • 90%的項(xiàng)目經(jīng)理都想不到,溝通成本原來(lái)可以這么小

    摘要:如果與相關(guān)人員的溝通不足,將很容易造成各做各事重復(fù)勞動(dòng),甚至造成不必要的損失。所以在項(xiàng)目管理上,項(xiàng)目經(jīng)理不得不花費(fèi)大量的精力在溝通上。 偶然回想起中學(xué)時(shí)候一次過(guò)生日,邀請(qǐng)朋友來(lái)家里,突然我就開始糾結(jié)到底要不要去買蛋糕。要是買,他在來(lái)的時(shí)候也買一個(gè)該怎么辦……我是不是應(yīng)該打個(gè)電話給他呢?可是打了我說(shuō)啥呢,說(shuō)你到哪兒了,你買蛋糕了嗎?莫名感覺有點(diǎn)尷尬……showImg(https://im...

    lei___ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<