Hello~大家好,這是我學(xué)習(xí)瀏覽器渲染機(jī)制時(shí)做的筆記,由于本人水平有限,所以在參考文章對(duì)于看不懂的便暫時(shí)沒有作筆記下來,參考文章:
CSDN咨詢?cè)朴?jì)算--有關(guān)網(wǎng)頁渲染,每個(gè)前端開發(fā)者都該知道的那點(diǎn)事
瀏覽器如何進(jìn)行渲染
- 處理html生成Dom(Document Object Model) Tree
- 處理css生成CSSOM(CSS Object Model) Tree
- 在文檔對(duì)象模型和CSS對(duì)象模型之上,創(chuàng)建一棵由一組待生成渲染的對(duì)象組成的渲染樹,即Render Tree
- 對(duì)Render樹進(jìn)行布局計(jì)算,即對(duì)渲染樹上的每個(gè)元素,計(jì)算它的坐標(biāo),稱之為布局。
- 繪制即Painting,渲染樹上的元素最終展示在瀏覽器里
性能優(yōu)化
(簡(jiǎn)單了解完瀏覽器渲染機(jī)制,我們可以據(jù)此進(jìn)行性能優(yōu)化)
首先了解一下重繪和重排
- Repaint****重繪 當(dāng)改變那些不會(huì)影響元素在網(wǎng)頁中的位置的元素樣式時(shí),譬如background-color(背景色), border-color(邊框色), visibility(可見性),瀏覽器只會(huì)用新的樣式將元素重繪一次(這就是重繪,或者說重新構(gòu)造樣式),此時(shí)布局沒有發(fā)生改變。
- Reflow重排 當(dāng)DOM變化影響了元素的幾何屬性(寬、高改變等等)
瀏覽器此時(shí)需要重新計(jì)算元素幾何屬性
并且頁面中其他元素的幾何屬性可能會(huì)受影響
這樣渲染樹就發(fā)生了改變,也就是重新構(gòu)造RenderTree渲染樹
觸發(fā)重排的情況
- 頁面初始渲染
- DOM操作(元素添加、刪除、修改或者元素順序的改變)
- 改變?cè)匚恢?,改變?cè)爻叽纾▽?、高、?nèi)外邊距、邊框等),改變?cè)貎?nèi)容(文本或圖片等)
- 瀏覽器窗口的操作(縮放,滾動(dòng))
- 添加或刪除樣式表
- 更改“類”的屬性
- 偽類激活(懸停)
優(yōu)化來啦
- 渲染隊(duì)列
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
如上,我們改變?cè)貙傩詴?huì)觸發(fā)重排,理論上會(huì)觸發(fā)四次重排,而實(shí)際上它只會(huì)進(jìn)行一次重排,這是因?yàn)槲覀儸F(xiàn)代的瀏覽器都有渲染隊(duì)列的機(jī)制 ,當(dāng)我改變了元素的一個(gè)樣式會(huì)導(dǎo)致瀏覽器發(fā)生重排或重繪時(shí),它會(huì)進(jìn)入一個(gè)渲染隊(duì)列,然后瀏覽器繼續(xù)往下看,如果下面還有樣式修改,同樣入列,直到下面沒有樣式修改,瀏覽器會(huì)按照渲染隊(duì)列批量執(zhí)行來優(yōu)化重排過程,一并修改樣式 。
如果我們現(xiàn)在想修改樣式后在后臺(tái)打印
div.style.left = '10px';
console.log(div.offsetLeft);
div.style.top = '10px';
console.log(div.offsetTop);
div.style.width = '20px';
console.log(div.offsetWidth);
div.style.height = '20px';
console.log(div.offsetHeight);
此時(shí)則會(huì)發(fā)生四次重排,而原因則是因?yàn)?strong>offsetLeft/Top/Width/Height
事實(shí)上,以下屬性或方法會(huì)刷新渲染隊(duì)列:
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- clientTop、clientLeft、clientWidth、clientHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- getComputedStyle()(IE中currentStyle)
我們修改為
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
console.log(div.offsetLeft);
console.log(div.offsetTop);
console.log(div.offsetWidth);
console.log(div.offsetHeight);
則優(yōu)化為一次重排了
- 減少http請(qǐng)求的次數(shù),根據(jù)功能和數(shù)據(jù)加載流程合并相應(yīng)的js,css,images 減少其請(qǐng)求的次數(shù)
- 減少帶寬,壓縮對(duì)應(yīng)的文件去掉一些空格,注釋提高相應(yīng)速度
- 把樣式表放在頭部?
- 腳本代碼引用加在<body>元素頁面內(nèi)容的后面,這樣在解析腳本之前,頁面的內(nèi)容將完全呈現(xiàn)在瀏覽器中,用戶會(huì)因?yàn)轱@示空白時(shí)間縮短而感覺打開頁面速度加快
- 將JavaScript和CSS存放到外部文件中,可以有效地將js, css文檔緩存到本地,當(dāng)你請(qǐng)求同樣包含以上js, css的腳本的時(shí)候,便無需重新下載,直接從緩存中載入了。此外,它還有一個(gè)很明顯的優(yōu)點(diǎn),就是增強(qiáng)了可重用性,你不必在每個(gè)頁面都重復(fù)地寫上一大串的代碼,造成資源和帶寬的浪費(fèi)。
-
盡量簡(jiǎn)化和優(yōu)化CSS選擇器,將嵌套程度保持在最低水平。
以下是CSS選擇器的性能排名(從最快者開始):
- 識(shí)別器:#id
- 類:.class
- 標(biāo)簽
- 相鄰兄弟選擇器:a + i
- 父類選擇器:ul> li
- 通用選擇器:*
- 屬性選擇:input[type="text"]
- 偽類和偽元素:a:hover
瀏覽器在處理選擇器時(shí)依照從右到左的原則,因此最右端的選擇器應(yīng)該是最快的:#id或則.class:
div * {...} // bad
.list li {...} // bad
.list-item {...} // good
#list .list-item {...} // good
- 盡量只給位置絕對(duì)或者固定的元素添加動(dòng)畫效果
Author:YY
Date:2017.7.10