-
瀏覽器加載時(shí)會(huì)發(fā)生什么
詳情可以查看這篇文章
首先瀏覽器會(huì)解析html 生成DOM樹;
接下來瀏覽器會(huì)將CSS部分解析成樣式結(jié)構(gòu)體;
完成以上兩步之后將 dom tree 和樣式結(jié)構(gòu)體結(jié)合,生成render tree;
在render tree生成后 瀏覽器開始繪制頁面。
需要注意的是
不會(huì)用于呈現(xiàn),而且不會(huì)影響呈現(xiàn)的隱藏節(jié)點(diǎn)不會(huì)包含到render tree
例如display:none,而visibility:hidden則會(huì)包含到render tree; -
回流何時(shí)發(fā)生的?
首先要明確
- 頁面至少會(huì)發(fā)生一次回流
- 回流必定重繪,重繪不一定回流
下面所有都會(huì)引起回流
- 調(diào)整窗口大小(Resizing the window)
- 改變字體(Changing the font)
- 增加或者移除樣式表(Adding or removing a stylesheet)
- 內(nèi)容變化,比如用戶在input框中輸入文字(Content changes, such as a user typing text inan input box)
- 激活 CSS 偽類,比如 :hover (IE 中為兄弟結(jié)點(diǎn)偽類的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
- 操作 class 屬性(Manipulating the class attribute)
- 腳本操作 DOM(A script manipulating the DOM)
- 計(jì)算 offsetWidth 和 offsetHeight 屬性(Calculating offsetWidth and offsetHeight)
- 設(shè)置 style 屬性的值 (Setting a property of the style attribute)
原文鏈接:回流與重繪:CSS性能讓JavaScript變慢?
-
如何減少回流帶來的影響,優(yōu)化性能
- 如果想設(shè)定元素的樣式,通過改變?cè)氐?class 名 (盡可能在 DOM 樹的最末端)(Change classes on the element you wish to style (as low in the dom tree as possible))
- 避免設(shè)置多項(xiàng)內(nèi)聯(lián)樣式(Avoid setting multiple inline styles)
- 應(yīng)用元素的動(dòng)畫,使用 position 屬性的 fixed 值或 absolute 值(Apply animations to elements that are position fixed or absolute)
- 權(quán)衡平滑和速度(Trade smoothness for speed)
- 避免使用table布局(Avoid tables for layout)
- 避免使用CSS的JavaScript表達(dá)式 (僅 IE 瀏覽器)(Avoid JavaScript expressions in the CSS (IE only))
原文鏈接:回流與重繪:CSS性能讓JavaScript變慢?
-
重繪repaint 重排reflows
重繪repaint 是一個(gè)元素外觀的改變所觸發(fā)的瀏覽器行為,例如改變vidibility、outline、背景色等屬性。瀏覽器會(huì)根據(jù)元素的新屬性重新繪制,使元素呈現(xiàn)新的外觀。重繪不會(huì)帶來重新布局,并不一定伴隨重排。
重排reflows 是更明顯的一種改變,可以理解為渲染樹需要重新計(jì)算。下面是常見的觸發(fā)重排的操作
-
DOM元素的幾何屬性變化
當(dāng)DOM元素的幾何屬性變化時(shí),渲染樹中的相關(guān)節(jié)點(diǎn)就會(huì)失效,瀏覽器會(huì)根據(jù)DOM元素的變化重建構(gòu)建渲染樹中失效的節(jié)點(diǎn)。之后,會(huì)根據(jù)新的渲染樹重新繪 制這部分頁面。而且,當(dāng)前元素的重排也許會(huì)帶來相關(guān)元素的重排。例如,容器節(jié)點(diǎn)的渲染樹改變時(shí),會(huì)觸發(fā)子節(jié)點(diǎn)的重新計(jì)算,也會(huì)觸發(fā)其后續(xù)兄弟節(jié)點(diǎn)的重排, 祖先節(jié)點(diǎn)需要重新計(jì)算子節(jié)點(diǎn)的尺寸也會(huì)產(chǎn)生重排。最后,每個(gè)元素都將發(fā)生重繪??梢?,重排一定會(huì)引起瀏覽器的重繪,一個(gè)元素的重排通常會(huì)帶來一系列的反 應(yīng),甚至觸發(fā)整個(gè)文檔的重排和重繪,性能代價(jià)是高昂的。 -
DOM樹的結(jié)構(gòu)變化
當(dāng)DOM樹的 結(jié)構(gòu)變化時(shí),例如節(jié)點(diǎn)的增減、移動(dòng)等,也會(huì)觸發(fā)重排。瀏覽器引擎布局的過程,類似于樹的前序遍歷,是一個(gè)從上到下從左到右的過程。通常在這個(gè)過程中,當(dāng)前 元素不會(huì)再影響其前面已經(jīng)遍歷過的元素。所以,如果在body最前面插入一個(gè)元素,會(huì)導(dǎo)致整個(gè)文檔的重新渲染,而在其后插入一個(gè)元素,則不會(huì)影響到前面的 元素。
3.** 獲取某些屬性**
瀏覽器引擎可能會(huì)針對(duì)重排做了優(yōu)化。比如Opera,它會(huì)等到有足夠 數(shù)量的變化發(fā)生,或者等到一定的時(shí)間,或者等一個(gè)線程結(jié)束,再一起處理,這樣就只發(fā)生一次重排。但除了渲染樹的直接變化,當(dāng)獲取一些屬性時(shí),瀏覽器為取得 正確的值也會(huì)觸發(fā)重排。這樣就使得瀏覽器的優(yōu)化失效了。這些屬性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用這些值時(shí)應(yīng)進(jìn)行緩存。
此外,改變?cè)氐囊恍邮剑{(diào)整瀏覽器窗口大小等等也都將觸發(fā)重排。
開發(fā)中,比較好的實(shí)踐是盡量減少重排次數(shù)和縮小重排的影響范圍。
如何減少重排帶來的影響
- 將多次改變樣式屬性的操作合并成一次操作。
- 將需要多次重排的元素,position屬性設(shè)為absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會(huì)影響到其他元素。例如有動(dòng)畫效果的元素就最好設(shè)置為絕對(duì)定位。
- 在內(nèi)存中多次操作節(jié)點(diǎn),完成后再添加到文檔中去。例如要異步獲取表格數(shù)據(jù),渲染到頁面。可以先取得數(shù)據(jù)后在內(nèi)存中構(gòu)建整個(gè)表格的html片段,再一次性添加到文檔中去,而不是循環(huán)添加每一行。
- 由于display屬性為none的元素不在渲染樹中,對(duì)隱藏的元素操作不會(huì)引發(fā)其他元素的重排。如果要對(duì)一個(gè)元素進(jìn)行復(fù)雜的操作時(shí),可以先隱藏它,操作完成后再顯示。這樣只在隱藏和顯示時(shí)觸發(fā)2次重排。
- 在需要經(jīng)常取那些引起瀏覽器重排的屬性值時(shí),要緩存到變量。
相關(guān)鏈接.