瀏覽器運(yùn)行機(jī)制圖:
瀏覽器的運(yùn)行機(jī)制:layout:布局;
1宫纬、構(gòu)建DOM樹(parse):渲染引擎解析HTML文檔,首先將標(biāo)簽轉(zhuǎn)換成DOM樹中的DOM node(包括js生成的標(biāo)簽)生成內(nèi)容樹(Content Tree/DOM Tree)赴精;
2完沪、構(gòu)建渲染樹(construct):解析對(duì)應(yīng)的CSS樣式文件信息(包括js生成的樣式和外部css文件),而這些文件信息以及HTML中可見的指令(如)携兵,構(gòu)建渲染樹(Rendering Tree/Frame Tree)疾掰;
3、布局渲染樹(reflow/layout):從根節(jié)點(diǎn)遞歸調(diào)用徐紧,計(jì)算每一個(gè)元素的大小静檬、位置等,給出每個(gè)節(jié)點(diǎn)所應(yīng)該在屏幕上出現(xiàn)的精確坐標(biāo)并级;
4拂檩、繪制渲染樹(paint/repaint):遍歷渲染樹,使用UI后端層來繪制每個(gè)節(jié)點(diǎn)嘲碧。
重繪(repaint或redraw):當(dāng)盒子的位置稻励、大小以及其他屬性,例如顏色愈涩、字體大小等都確定下來之后望抽,瀏覽器便把這些原色都按照各自的特性繪制一遍加矛,將內(nèi)容呈現(xiàn)在頁面上。
重繪是指一個(gè)元素外觀的改變所觸發(fā)的瀏覽器行為煤篙,瀏覽器會(huì)根據(jù)元素的新屬性重新繪制斟览,使元素呈現(xiàn)新的外觀。
? 觸發(fā)重繪的條件:改變?cè)赝庥^屬性舰蟆。如:color趣惠,background-color等。
注意:table及其內(nèi)部元素可能需要多次計(jì)算才能確定好其在渲染樹中節(jié)點(diǎn)的屬性值身害,比同等元素要多花兩倍時(shí)間味悄,這就是我們盡量避免使用table布局頁面的原因之一。
重排(重構(gòu)/回流/reflow):當(dāng)渲染樹中的一部分(或全部)因?yàn)樵氐囊?guī)模尺寸塌鸯,布局侍瑟,隱藏等改變而需要重新構(gòu)建, 這就稱為回流(reflow)。每個(gè)頁面至少需要一次回流丙猬,就是在頁面第一次加載的時(shí)候涨颜。
重繪和重排的關(guān)系:在回流的時(shí)候,瀏覽器會(huì)使渲染樹中受到影響的部分失效茧球,并重新構(gòu)造這部分渲染樹庭瑰,完成回流后,瀏覽器會(huì)重新繪制受影響的部分到屏幕中抢埋,該過程稱為重繪弹灭。
所以,重排必定會(huì)引發(fā)重繪揪垄,但重繪不一定會(huì)引發(fā)重排穷吮。
? 觸發(fā)重排的條件:任何頁面布局和幾何屬性的改變都會(huì)觸發(fā)重排,比如:
1饥努、頁面渲染初始化捡鱼;(無法避免)
2、添加或刪除可見的DOM元素酷愧;
3驾诈、元素位置的改變,或者使用動(dòng)畫溶浴;
4翘鸭、元素尺寸的改變——大小,外邊距戳葵,邊框就乓;
5、瀏覽器窗口尺寸的變化(resize事件發(fā)生時(shí));
6生蚁、填充內(nèi)容的改變噩翠,比如文本的改變或圖片大小改變而引起的計(jì)算值寬度和高度的改變;
7邦投、讀取某些元素屬性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )
重繪重排的代價(jià):耗時(shí)伤锚,導(dǎo)致瀏覽器卡慢。
優(yōu)化:
1志衣、瀏覽器自己的優(yōu)化:瀏覽器會(huì)維護(hù)1個(gè)隊(duì)列屯援,把所有會(huì)引起回流、重繪的操作放入這個(gè)隊(duì)列念脯,等隊(duì)列中的操作到了一定的數(shù)量或者到了一定的時(shí)間間隔狞洋,瀏覽器就會(huì)flush隊(duì)列,進(jìn)行一個(gè)批處理绿店。這樣就會(huì)讓多次的回流吉懊、重繪變成一次回流重繪。
2假勿、我們要注意的優(yōu)化:我們要減少重繪和重排就是要減少對(duì)渲染樹的操作借嗽,則我們可以合并多次的DOM和樣式的修改。并減少對(duì)style樣式的請(qǐng)求转培。
(1)直接改變?cè)氐腸lassName
(2)display:none恶导;先設(shè)置元素為display:none;然后進(jìn)行頁面布局等操作浸须;設(shè)置完成后將元素設(shè)置為display:block惨寿;這樣的話就只引發(fā)兩次重繪和重排;
(3)不要經(jīng)常訪問瀏覽器的flush隊(duì)列屬性羽戒;如果一定要訪問,可以利用緩存虎韵。將訪問的值存儲(chǔ)起來易稠,接下來使用就不會(huì)再引發(fā)回流;
(4)使用cloneNode(true or false) 和 replaceChild 技術(shù)包蓝,引發(fā)一次回流和重繪驶社;
(5)將需要多次重排的元素,position屬性設(shè)為absolute或fixed测萎,元素脫離了文檔流亡电,它的變化不會(huì)影響到其他元素;
(6)如果需要?jiǎng)?chuàng)建多個(gè)DOM節(jié)點(diǎn)硅瞧,可以使用DocumentFragment創(chuàng)建完后一次性的加入document份乒;
varfragment = document.createDocumentFragment();
varli = document.createElement('li');
li.innerHTML = 'apple';
fragment.appendChild(li);
varli = document.createElement('li');
li.innerHTML = 'watermelon';
fragment.appendChild(li);
document.getElementById('fruit').appendChild(fragment);
(7)盡量不要使用table布局。