摘要:寫在金三銀四之際。一個節點觸發了,瀏覽器會檢查中其他所有節點的顯示方式一個節點觸發了會導致它的祖先節點,后代節點以及在它之后的節點全部。對性能的影響大于。解決方式控制我們無力去改變,對性能損害的程度,我們能做的只有減少它們發生的次數。
寫在金三銀四之際。萬惡之源——無知
因為種種原因想要謀求新的發展,不得已翻起了塵封已久的高程書;寫起了各種經典CSS布局;回顧起記憶略顯模糊的幾個項目。感慨著太多太多的知識點自己都不夠深入甚至缺乏認識,卻又不能急功近利,囫圇吞棗。
牢騷發完了,苦水吐完了,進入正題。
回流(reflow),重繪(repaint)都是瀏覽器更新頁面視圖的方式,區別在于:
對于元素視覺上的改變(如改變outline,background-color,visibility等)會觸發repaint;
對于元素布局上的改變(增刪節點,觸發resize事件,修改style屬性等)會觸發reflow;
repaint和reflow是DOM操作影響性能的主要原因。一個節點觸發了repaint,瀏覽器會檢查DOM Tree中其他所有節點的顯示方式;一個節點觸發了reflow會導致它的祖先節點,后代節點以及在它之后的節點全部reflow。reflow對性能的影響大于repaint。
一個前端開發人員對這些概念一無所知是一件很恐怖的事情,想想他在寫代碼的時候不知道哪些操作會對性能造成影響,可能會出現這種情況:
var toChange = document.getElementById("target"); toChange.style.background = "#333"; toChange.style.color = "#fff"; toChange.style.border = "1px solid #00f";
這無疑是可以優化的,下面我們來看看如何減少reflow,repaint的次數。
解決方式——控制我們無力去改變repaint,reflow對性能損害的程度,我們能做的只有減少它們發生的次數。
動畫時時刻刻都在操作著DOM,為了避免動畫使得其他節點也在時時刻刻reflow,可以將動畫所在的元素設為position: fixed或者position: absolute,使其脫離文檔流,這個元素reflow時不會影響其他節點的布局,雖然還是會產生repaint,但相對來說得到了優化。
能一次完成的操作就不要分兩次。比如說添加多個節點時使用DocumentFragment:
var docFragm = document.createDocumentFragment(); var elem, contents; for(var i = 0; i < textlist.length; i++) { elem = document.createElement("p"); contents = document.createTextNode(textlist[i]); elem.appendChild(contents); docFragm.appendChild(elem); } document.body.appendChild(docFragm);
再比如像上面style那個例子,如果已知變化后樣式,將這些樣式寫成一個class,再去改變元素的class或者直接修改cssText屬性,這兩種方式都將多次reflow縮減為一次。
對復制品進行操作也是一種解決方案,比如需要對已有節點進行DOM操作使用cloneNode():
var original = document.getElementById("container"); var cloned = original.cloneNode(true); cloned.setAttribute("width", "50%"); var elem, contents; for(var i = 0; i < textlist.length; i++) { elem = document.createElement("p"); contents = document.createTextNode(textlist[i]); elem.appendChild(contents); cloned.appendChild(elem); } original.parentNode.replaceChild(cloned, original);
使用cloneNode()要注意的是,唯一的參數代表是否進行深復制。另外cloneNode()無法復制事件監聽函數,以及表單控件的value。
又比如獲取offsetWidth,getComputedStyle()這些取值操作每次都會觸發reflow,在第一次調用時存起來也是復制的一種。
在做好了其他優化措施的前提下想要進一步提升性能有時需要舍棄,比如減小動畫幀數,即增大動畫函數執行的間隔,這樣動畫流暢程度會降低,但整個應用的性能得到了提升。
減少table的使用,table造成的reflow是其他塊級元素的三倍;
盡量避免改變DOM Tree中高層節點的class,減小reflow的影響;
利用各種選擇器規則減少待操作節點的數量;
最后,我認為理解reflow和repaint的原理及觸發情況是十分重要的,在寫每一行代碼時都應該明確它對性能的影響。
參考文章:
REFLOWS & REPAINTS: CSS PERFORMANCE MAKING YOUR JAVASCRIPT SLOW?
Effecitve JavaScript
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93407.html
摘要:之后,如果渲染樹發生了變動,那么可能會觸發回流或重繪中的一個或二者。在書寫時要避免不必要的層級,書寫時避免嵌套過深規則過于復雜,尤其是后代選擇器,匹配選擇器也會耗費更多的。 剛入行前端的時候是不是經常看到有文章說盡量不要用CSS通配符*,CSS選擇器層疊最好不要超過三層,HTML少使用table,結構也要盡量簡單一些...這一切說的不無道理,過多的使用確實會造成瀏覽器渲染的性能降低,當...
摘要:前言最近在研究,接著就研究回顧起回流與重繪了。回流與重繪,好像大家都很熟悉的樣子,但是要具體來說說,又說不出什么來。注意回流必將引起重繪,而重繪不一定會引起回流。 前言 最近在研究virtual dom,接著就研究回顧起回流(reflow)與重繪(repaint)了。 回流與重繪,好像大家都很熟悉的樣子,但是要具體來說說,又說不出什么來。下面我是我稍做的整理: 瀏覽器渲染流程 在理解這...
摘要:前言最近在研究,接著就研究回顧起回流與重繪了。回流與重繪,好像大家都很熟悉的樣子,但是要具體來說說,又說不出什么來。注意回流必將引起重繪,而重繪不一定會引起回流。 前言 最近在研究virtual dom,接著就研究回顧起回流(reflow)與重繪(repaint)了。 回流與重繪,好像大家都很熟悉的樣子,但是要具體來說說,又說不出什么來。下面我是我稍做的整理: 瀏覽器渲染流程 在理解這...
閱讀 3872·2021-09-27 13:35
閱讀 1069·2021-09-24 09:48
閱讀 2899·2021-09-22 15:42
閱讀 2339·2021-09-22 15:28
閱讀 3145·2019-08-30 15:43
閱讀 2609·2019-08-30 13:52
閱讀 2971·2019-08-29 12:48
閱讀 1451·2019-08-26 13:55