當咱們對dom 進行修改當時候會引起它外觀(樣式)上的改變時,就會觸發迴流或重繪。
這個過程本質上仍是由於咱們對 DOM 的修改觸發了渲染樹(Render Tree)的變化所致使的瀏覽器
1.根據 HTML 結構生成 DOM 樹
2.根據 CSS 生成 CSSOM
3.將 DOM 和 CSSOM 整合造成 RenderTree
4.根據 RenderTree 開始渲染和展現
5.遇到<script>時,會執行並阻塞渲染緩存
因此由此來看 重繪不必定致使迴流,迴流必定會致使重繪 前面咱們說迴流和重繪是會對dom進行修改,會消耗性能,因此咱們要儘量減小回流和重繪的次數。dom
要減小回流和重繪的發生,咱們得知道那些操做會致使,佈局
1.改變dom元素的幾何屬性
常見的幾何屬性有 width、height、padding、margin、left、top、border 等等。此處再也不給你們一一列舉。有的文章喜歡羅列屬性表格,但我相信我今天列出來你們也不會看、看了也記不住(由於太多了)。我本身也不會去記這些——其實確實不必記,️一個屬性是否是幾何屬性、會不會致使空間佈局發生變化,你們寫樣式的時候徹底能夠經過代碼效果看出來。
2.改變dom樹的結構
主要指的是增長或減小dom節點,移動等操做。
3.獲取一些特定屬性的值
當你要用到像這樣的屬性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 時,你就要注意了!性能
「像這樣」的屬性,究竟是像什麼樣?——這些值有一個共性,就是須要經過即時計算獲得。所以瀏覽器爲了獲取這些值,也會進行迴流。spa
除此以外,當咱們調用了 getComputedStyle 方法,或者 IE 裏的 currentStyle 時,也會觸發迴流。原理是同樣的,都爲求一個「即時性」和「準確性」。code
迴流比重繪更加消耗性能,付出的代價更高隊列
1.避免逐條改變樣式,使用類名去合併樣式ip
const container = document.getElementById('container') container.style.width = '100px' container.style.height = '200px' container.style.border = '10px solid red' container.style.color = 'red'
將這段代碼用 類名去合併get
.basic_style { width: 100px; height: 200px; border: 10px solid red; color: red; } const container = document.getElementById('container') container.classList.add('basic_style')
2.將 DOM 「離線」
let container = document.getElementById('container') container.style.display = 'none' container.style.width = '100px' container.style.height = '200px' container.style.border = '10px solid red' container.style.color = 'red' ...(省略了許多相似的後續操做) container.style.display = 'block'
繼續用上面的代碼來講明這個問題
const container = document.getElementById('container') container.style.width = '100px' container.style.height = '200px' container.style.border = '10px solid red' container.style.color = 'red'
從這段代碼中發生了幾回迴流與重繪呢?在這裏改變了幾何屬性的有width, height, border。改變顏色的red,因此致使了三次迴流和一次重繪,一眼看過去是很正確的,實際上是忽略了瀏覽器自身:並無那麼簡單!這段代碼實際上只進行了一次迴流和一次重繪,爲何和咱們開始想的不同呢?由於現代瀏覽器是很聰明的。瀏覽器本身也清楚,若是每次 DOM 操做都即時地反饋一次迴流或重繪,那麼性能上來講是扛不住的。因而它本身緩存了一個 flush 隊列,把咱們觸發的迴流與重繪任務都塞進去,待到隊列裏的任務多起來、或者達到了必定的時間間隔,或者「不得已」的時候,再將這些任務一口氣出隊。所以咱們看到,上面就算咱們進行了 4 次 DOM 更改,也只觸發了一次 Layout 和一次 Paint。可是也有例外,由於有的時候咱們須要精確獲取某些樣式信息,下面這些:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 這些屬性有很強的「即時性」。當咱們訪問這些屬性時,瀏覽器會爲了得到此時此刻的、最準確的屬性值,而提早將 flush 隊列的任務出隊——這就是所謂的「不得已」時刻。