為了讓項目的運行效率更高,減少開銷,需要對重排、回流、重繪有一定的了解。
重排和回流其實是一回事。
瀏覽器渲染
瀏覽器在渲染頁面的時候,大致是以下幾個步驟:
1. 解析html生成DOM樹,解析css,生成CSSOM樹,將DOM樹和CSSOM樹結合,生成渲染樹;
2. 根據(jù)渲染樹,瀏覽器可以計算出網頁中有哪些節(jié)點,各節(jié)點的CSS以及從屬關系 - 回流
3. 根據(jù)渲染樹以及回流得到的節(jié)點信息,計算出每個節(jié)點在屏幕中的位置 - 重繪
4. 最后將得到的節(jié)點位置信息交給瀏覽器的圖形處理程序,讓瀏覽器中顯示頁面
回流
回流:英文叫reflow,指的是當渲染樹中的節(jié)點信息發(fā)生了大小、邊距等問題,需要重新計算各節(jié)點和css具體的大小和位置。
例:在css中對一個div修飾的樣式中,使用了寬度50%,此時需要將50%轉換為具體的像素,這個計算的過程,就是回流的過程。
容易造成回流的操作:
1、布局流相關操作
· 盒模型的相關操作會觸發(fā)重新布局
· 定位相關操作會觸發(fā)重新布局
· 浮動相關操作會觸發(fā)重新布局
2、改變節(jié)點內的內容
改變節(jié)點的結構或其中的文本結構會觸發(fā)重新布局
3、css
· width
· height
· padding
· border
· margin
· position
· top
· left
· bottom
· right
· float
· clear
· text-align
· vertical-align
· line-height
· font-weight
· font-size
· font-family
· overflow
· white-space
重繪
重繪:英文叫repaint,當節(jié)點的部分屬性發(fā)生變化,但不影響布局,只需要重新計算節(jié)點在屏幕中的絕對位置并渲染的過程,就叫重繪。比如:改變元素的背景顏色、字體顏色等操作會造成重繪。
回流的過程在重繪的過程前面,所以回流一定會重繪,但重繪不一定會引起回流。
容易造成重繪操作的css:
· color
· border-style
· border-radius
· text-decoration
· box-shadow
· outline
· background
每次回流都會對瀏覽器造成額外的計算消耗,所以瀏覽器對于回流和重繪有一定的優(yōu)化機制。瀏覽器通常都會將多次回流操作放入一個隊列中,等過了一段時間或操作達到了一定的臨界值,然后才會挨個執(zhí)行,這樣能節(jié)省一些計算消耗。但是在獲取布局信息操作的時候,會強制將隊列清空,也就是強制回流,比如訪問或操作以下或方法時:
· offsetTop
· offsetLeft
· offsetWidth
· offsetHeight
· scrollTop
· scrollLeft
· scrollWidth
· scrollHeight
· clientTop
· clientLeft
· clientWidth
· clientHeight
· getComputedStyle()
這些屬性或方法都需要得到最新的布局信息,所以瀏覽器必須去回流執(zhí)行。因此,在項目中,盡量避免使用上述屬性或方法,如果非要使用的時候,也盡量將值緩存起來,而不是一直獲取。
減少回流和重繪
合并樣式修改
減少造成回流的次數(shù),如果要給一個節(jié)點操作多個css屬性,而每一個都會造成回流的話,盡量將多次操作合并成一個,例:
操作div的3個css屬性,分別是padding、border、margin,此時就可以考慮將多次操作合并為一次。
方法一:使用style的cssText:
方法二:將這幾個樣式定義給一個類名,然后給標簽添加類名:
批量操作DOM
當對DOM有多次操作的時候,需要使用一些特殊處理減少觸發(fā)回流,其實就是對DOM的多次操作,在脫離標準流后,對元素進行的多次操作,不會觸發(fā)回流,等操作完成后,再將元素放回標準流。
脫離標準流的操作有以下3中:
1. 隱藏元素
2. 使用文檔碎片
3. 拷貝節(jié)點
例:下面對DOM節(jié)點的多次操作,每次都會觸發(fā)回流
這樣每次給ul中新增一個li的操作,每次都會觸發(fā)回流。
方法一:隱藏ul后,給ul添加節(jié)點,添加完成后再將ul顯示
此時,在隱藏ul和顯示ul的時候,觸發(fā)了兩次回流,給ul添加每個li的時候沒有觸發(fā)回流。
方法二:創(chuàng)建文檔碎片,將所有l(wèi)i先放在文檔碎片中,等都放進去以后,再將文檔碎片放在ul中
方法三:將ul拷貝一份,將所有l(wèi)i放在拷貝中,等都放進去以后,使用拷貝替換掉ul
避免多次觸發(fā)布局
如下回到頂部的操作:
每隔20毫秒都會重新獲取滾動過的距離,每次都會觸發(fā)回流,代碼優(yōu)化如下:
只獲取一次,每次都讓數(shù)字遞增,避免每次都獲取滾動過的距離。
對于頁面中比較復雜的動畫,盡量將元素設置為絕對定位,操作元素的定位屬性,這樣只有這一個元素會回流,如果不是定位的話,容易引起其父元素以及子元素的回流。
更多關于html5培訓的問題,歡迎咨詢千鋒教育在線名師,如果想要了解我們的師資、課程、項目實操的話可以點擊咨詢課程顧問,獲取試聽資格來試聽我們的課程,在線零距離接觸千鋒教育大咖名師,讓你輕松從入門到精通。