1.介紹
為什么會(huì)寫一篇這樣的文章呢,因?yàn)樵倏赐赀@樣一篇測(cè)試之后感覺重繪和回流對(duì)瀏覽器的性能影響還是很大的董虱。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<style>
.box-ps,.box-tf{position:absolute;top:0;left:0;width:100px;height:100px;background-color:red;}
.box-ps{-webkit-animation:box-ps 2s linear;}
.box-tf{-webkit-animation:box-tf 2s linear;}
@-webkit-keyframes box-ps{
0%{
left:0;
}100%{
left:500px;
}
}
@-webkit-keyframes box-tf{
0%{
-webkit-transform:translate(0,0);
}100%{
-webkit-transform:translate(500px,0);
}
}
</style>
<div class="box-ps"></div>
<div class="box-tf"></div>
</html>
使用left瀏覽器性能使用translate瀏覽器性能
可以看到left一直在回流重繪咙轩,但是translate就不一樣啦,這是因?yàn)镃SS3做了很多優(yōu)化。
2.瀏覽器渲染機(jī)制
- 瀏覽器把我們獲取的html代碼分析成一個(gè)dom樹,html中的每個(gè)tag都是dom樹中的一個(gè)節(jié)點(diǎn)泽篮,根節(jié)點(diǎn)就是我們常用的document對(duì)象。dom樹里面包含了所有的html tag柑船,包含display:none的元素,還有js動(dòng)態(tài)添加的元素等泼各。
- 瀏覽器把所有樣式(主要包含CSS和瀏覽器的樣式設(shè)置)解析成樣式結(jié)構(gòu)體鞍时,在解析的過程中會(huì)去掉瀏覽器不能識(shí)別的樣式,比如IE會(huì)去掉-moz開頭的樣式扣蜻。
- dom tree和樣式結(jié)構(gòu)體(cssom)結(jié)合后構(gòu)建呈現(xiàn)樹(render逆巍,tree)render tree有點(diǎn)像dom的樹,但是還是有區(qū)別的莽使,render的樹可以識(shí)別樣式锐极,每個(gè)node都有自己的樣式,而且render tree不包含隱藏的節(jié)點(diǎn)(比如display:none的節(jié)點(diǎn)芳肌,還有head節(jié)點(diǎn))因?yàn)檫@些節(jié)點(diǎn)不會(huì)用于呈現(xiàn)灵再,并且不會(huì)影響呈現(xiàn)的,所以就不會(huì)包含到render tree中亿笤。
3.什么是重繪和回流
1.當(dāng)render tree 中的一部分(或者全部)因?yàn)樵氐囊?guī)模尺寸翎迁,布局,隱藏等改變而需要重新構(gòu)建净薛。這就稱為回流汪榔,每個(gè)頁面至少需要一次回流,那就是頁面第一次加載的時(shí)候肃拜。
2.當(dāng)render tree 中的一些元素需要更新屬性時(shí)痴腌,而這些屬性只影響元素的外觀雌团,風(fēng)格,而不會(huì)影響布局時(shí)士聪,就叫做重繪锦援。
回流一定會(huì)重繪,但是重繪不一定回流
4.那些情況會(huì)發(fā)生重繪和回流
- 頁面第一次加載的時(shí)候
- 改變字體戚嗅,改變?cè)爻叽纾ㄈ绻桓淖冏煮w顏色雨涛,元素背景顏色那么只觸發(fā)重繪)
- 改變?cè)乩锩鎯?nèi)容的時(shí)候(比如在input里面輸入文字)
- 添加/刪除可見DOM元素(注意:如果元素本身就display:none的元素不會(huì)發(fā)生重排;visibility:hidden的元素顯示或隱藏不影響重排)
- fiexd定位的元素懦胞,在拖動(dòng)滾動(dòng)條的時(shí)候會(huì)一直發(fā)生回流替久。
- 調(diào)整窗口大小的時(shí)候
- 計(jì)算offertWidth 和 offsetHeight屬性的時(shí)候
5. 如果減少回流和重繪
- 使用tranform代替top
- 使用visibility 代替 display:none(前者只會(huì)重繪,后者會(huì)回流)
- 避免使用table布局(可能一個(gè)很小的改動(dòng)會(huì)造成整個(gè)table的重新布局)
- 盡可能在dom樹末端改變class(回流是不可避免的躏尉,但可以減少其影響蚯根。盡可能在DOM樹末端改變class,可以限制回流的范圍胀糜,使其影響盡可能少的節(jié)點(diǎn))
- 避免設(shè)置多層內(nèi)聯(lián)樣式(比如 div > span > a颅拦,因?yàn)闉g覽器要去遞歸尋找,比較復(fù)雜教藻。)
- 將動(dòng)畫應(yīng)用到position屬性為absolute或者fixed的元素上(避免影響其他元素布局距帅,這樣只是重繪,而不是回流括堤,同時(shí)控制動(dòng)畫可以選擇requestAnimationFrame)
- 避免使用CSS表達(dá)式
- 避免頻繁的操作dom(你可以js創(chuàng)建一個(gè)元素碌秸,完成所有dom操作在添加到頁面當(dāng)中)
- 避免頻繁的讀取會(huì)引發(fā)回流/重繪的屬性(如果要多次使用可以保存起來 const width = element.offertWidth)