頁(yè)面呈現(xiàn)流程
- 瀏覽器會(huì)將獲取到的HTML代碼解析成一個(gè)DOM樹(shù)(包括display: none的元素)
- 在DOM樹(shù)的基礎(chǔ)上根據(jù)節(jié)點(diǎn)的幾何屬性(margin/padding/width/height等)生成render樹(shù)(不包括display: none、head節(jié)點(diǎn)但是會(huì)包含visibility:hidden節(jié)點(diǎn))
-
在render樹(shù)的基礎(chǔ)上進(jìn)一步渲染樣式
repaint、reflow概念
回流(reflow):當(dāng)render樹(shù)種的元素因?yàn)榇笮≡彻妫季殖挠悖[藏买喧、增減等原因而引起的重建叫做回流
重繪(repaint):當(dāng)元素的一部分屬性發(fā)生變化的時(shí)候,會(huì)影響外觀但是不會(huì)引起布局變化(比如background-color)而重新渲染的過(guò)程叫重繪
引起回流的原因
- 頁(yè)面初始化渲染
- DOM節(jié)點(diǎn)的增加和刪除
- 元素位置發(fā)生改變
- 元素幾何屬性發(fā)生變化 - border匆赃、width淤毛、height、padding算柳、margin
- 瀏覽器窗口發(fā)生變化(resize)
- 獲取某些屬性 - offsetTop低淡、offsetLeft、offsetWidth瞬项、offsetHeight蔗蹋、scrollTop、scrollLeft囱淋、scrollWidth猪杭、scrollHeight、clientTop妥衣、clientLeft皂吮、clientWidth、clientHeight税手、getComputedStyle() (currentStyle in IE)
var s = document.body.style;
s.padding = "2px"; // 回流 + 重繪
s.border = "1px solid red"; // 再一次 回流+重繪
s.color = "blue"; // 再一次重繪
s.backgroundColor = "#ccc"; // 再一次 重繪
s.fontSize = "14px"; // 再一次 回流+重繪
// 添加node蜂筹,再一次 回流+重繪
document.body.appendChild(document.createTextNode('abc!'));
上面代碼一共引起了4次回流和6次重繪,但是瀏覽器并不會(huì)每一條js語(yǔ)句就執(zhí)行一次芦倒,而是等隊(duì)列中的操作到了一定的數(shù)量或者到了一定的時(shí)間間隔艺挪,瀏覽器就會(huì)flush對(duì)象,進(jìn)行批量處理兵扬,這樣就會(huì)讓多次回流麻裳、重繪變成一次回流重繪。
當(dāng)我們?nèi)カ@取第六點(diǎn)那些屬性的時(shí)候周霉,瀏覽器為了能給你返回一個(gè)比較精確的答案掂器,他會(huì)提前flush隊(duì)列,因?yàn)殛?duì)列中可能會(huì)有影響這些值的操作俱箱,所以獲取這些屬性也會(huì)引起回流
優(yōu)化
- 使用class將多次改變樣式屬性的操作合并成一次操作
var changeDiv = document.getElementById('changeDiv');
changeDiv.style.color = '#093';
changeDiv.style.background = '#eee';
changeDiv.style.height = '200px';
// 可以添加一個(gè)class
div.changeDiv {
background: #eee;
color: #093;
height: 200px;
}
為這個(gè)節(jié)點(diǎn)添加這個(gè)className
document.getElementById('changeDiv').className = 'changeDiv';
- 讓要操作的元素進(jìn)行"離線處理"国瓮,處理完后一起更新
a)使用DocumentFragment進(jìn)行緩存操作,引發(fā)一次回流和重繪
b)使用display:none狞谱,如果要對(duì)一個(gè)元素進(jìn)行復(fù)雜操作乃摹,可以先隱藏他,操作完成之后在顯示跟衅,這樣只引發(fā)兩次回流和重繪
c)使用cloneNode(true/false)和replaceChild孵睬,引發(fā)一次回流和重繪 - 將需要多次重排的元素,position屬性設(shè)置為absolute或者fixed伶跷,這樣此元素會(huì)脫離文檔流掰读,他的變化不會(huì)影響到其他元素秘狞。例如有動(dòng)畫效果的元素最好設(shè)置為絕對(duì)定位。
- 在內(nèi)存中多次操作節(jié)點(diǎn)蹈集,可以一起操作完成之后再添加到文檔中去烁试。
- 在需要經(jīng)常獲取那些引起瀏覽器回流的屬性值是,可以緩存到變量中拢肆,而不是每次去重新獲取减响。
參考文檔: