參考自 (MDN).javascript
構建渲染樹,瀏覽器須要作一下工做:java
第一步遍歷節點的時候,須要知道什麼節點是不可見的。web
注意: 渲染樹只包含可見的節點瀏覽器
當 Render Tree
中部分或所有, 因元素的尺寸、佈局、隱藏等改變而須要從新構建,瀏覽器從新渲染的過程稱爲 迴流。緩存
會致使迴流的操做:函數
DOM
元素。CSS
僞類 (eg: :hover
)。一些經常使用且會致使迴流的屬性和方法。佈局
clientWidth
、clientHeight
、clientTop
、clientLeft
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
scrollWidth
、scrollHeight
、scrollTop
、scrollLeft
scrollIntoView()
、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
當頁面中元素樣式的改變並不影響b佈局時(eg:color
、background-color
等),瀏覽器會將新樣式賦予給元素並從新繪製它,這個過程稱爲重繪。性能
一句話: 迴流必將引發重繪,重繪不必定會引發迴流。字體
有時即便僅僅迴流一個單一的元素,它的父元素以及任何跟隨它的元素也會產生迴流。優化
現代瀏覽器會對頻繁的迴流或重繪操做進行優化:
瀏覽器會維護一個隊列,把全部引發迴流和重繪的操做放入隊列中,若是隊列中的任務數量或者時間間隔達到一個閾值的,瀏覽器就會將隊列清空,進行一次批處理,這樣能夠把屢次迴流和重繪變成一次。
當你訪問如下屬性或方法時,瀏覽器會馬上清空隊列:
clientWidth
、clientHeight
、clientTop
、clientLeft
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
scrollWidth
、scrollHeight
、scrollTop
、scrollLeft
scrollIntoView()
、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
由於隊列中可能會有影響到這些屬性或方法返回值的操做,即便你但願獲取的信息與隊列中操做引起的改變無關,瀏覽器也會強行清空隊列,確保你拿到的值是最精確的。
table
佈局 (儘可能不要使用表格佈局,若是沒有定寬表格一列的寬度由最寬的一列決定,那麼極可能在最後一行的寬度超出以前的列寬,引發總體迴流形成table可能須要屢次計算才能肯定好其在渲染樹中節點的屬性,一般要花3倍於同等元素的時間。)// bad
for (var i = 0; i < len; i++) {
el.style.left = el.offsetLeft + x + "px";
el.style.top = el.offsetTop + y + "px";
}
// good
var x = el.offsetLeft,
y = el.offsetTop;
for (var i = 0; i < len; i++) {
x += 10;
y += 10;
el.style = x + "px";
el.style = y + "px";
}
複製代碼
let box = document.getElementById("box").style;
// bad
box.color = "red"; // 重繪
box.size = "14px"; // 迴流、重繪
// good
box.bord = '1px solid red'
複製代碼
DOM
,建立一個documentFragment
,在它上面應用全部 DOM
操做,最後再把它添加到文檔中。DocumentFragment,文檔片斷接口,表示一個沒有父級文件的最小文檔對象. 與 Document
最大的區別是由於 DocumentFragment
不是真實 DOM
樹的一部分,它的變化不會觸發 DOM
樹的(從新渲染) ,且不會致使性能等問題。
可使用 document.createDocumentFragment
方法或者構造函數來建立一個空的 DocumentFragment
.