javascript
js hover 触发事件_为什么说JS的DOM操作很耗性能
想問這樣的問題,其實是自己心中沒有個譜,一直用 js 計算性能來衡量 瀏覽器dom 操作性能。js性能和瀏覽器性能其實是兩碼事。
這個問題很抽象,它里面涉及挺多個小的知識點。
重申一點,js 操作 Dom 很耗性能,其實是在說很耗瀏覽器性能,具體和 js計算 性能沒多大的關系;
文章大致行文思路如下:
- URL從輸入到頁面展示的過程
- 渲染HTML的過程
- 為什么很“慢”
- 重排
- 重繪
- 優化方案
URL從輸入到頁面展示的過程
這個是一個很常見的面試問題。
我這邊只是講解一個粗略的過程。相當于是了解,知道渲染一個頁面的工作流程,加深大家對瀏覽器性能的概念。
1、用戶輸入 Url 后,瀏覽器會根據 url 在本地查找緩存,若是有緩存,直接跳到第5步,若沒有緩存則解析出主機名。
2、瀏覽器根據主機名查找出 ip。
先查找本地 DNS 緩存列表,如果有,則進入第4步;若沒有,則想瀏覽器默認的 DNS 域名服務器發起請求,獲取倒 ip,并緩存在本地 DNS。
3、解析Url獲取倒端口號。
4、拿到 ip+端口號,則開始建立起一條鏈接目標服務氣的 TCP 鏈接,也就是“三次握手”。
5、瀏覽器向服務器發送一條 HTTP 請求報文
6、服務器向瀏覽器返回一條 HTTP 響應報文。
7、關閉連接 瀏覽器解析文檔。
8、如果文檔中有資源則重復5、6、7、8動作,直至資源全部加載完畢。
以上步驟簡述了瀏覽器從輸入url到最后頁面呈現的大致過程。
在以前,網絡帶寬還比較小的時候,前端這方面是要盡量減小首次進入頁面的 http請求次數,以提升網頁的打開速度,同時也減小服務器的壓力。
在那個時代,會嚴格要求前端開發工程師做小圖片的整合,減少頁面img的請求次數。
針對這一點,建議當代的前端設計師為了用戶體驗,要盡量注意以下幾點:
- 盡量減小首次進入頁面的 http請求次數,特別是在一些并發量大的業務場景。
- 一些活動頁面,大多數展示已經用圖片替代,請盡量減小圖片的大小;
- 盡量告知后端同學,對于返回的數據,支持 gzip 編碼。這樣js、css的請求數據可以大大減小。
渲染 HTML 的過程
當瀏覽器下載完所有頁面 HTML 標記,JavaScript,CSS,圖片之后,它解析文件并創建兩個內部數據結構:一個DOM Tree樹表示頁面結構,一個是 CSSOM Tree表示DOM節點如何顯示。
把DOM Tree 和 CSSOM Tree結合在一起,就成為 Render Tree(渲染樹)。
瀏覽器根據渲染樹計算每一個節點的幾何信息。這個就叫做重排(Relayout,更專業的叫法應該是回流(Reflow)。
根據計算好的幾何信息,繪制頁面。這個就叫做重繪(Repainting)。
重繪是一個非常昂貴的操作。瀏覽器完成一個dom操作,大多時間都是花費在重繪上面的。
什么叫做重排、重繪?在文章后面有介紹。
為什么很“慢”
通過學習,我總結出來,有兩個方面。
1)瀏覽器響應 DOM操作 需要一定的成本。程序跑起來都是要花時間的嘛,對我們開發者來說,在乎的是這個時間的長短,更直觀的說法就是卡頓是否肉眼可見。
2)第二點的說法更關乎技術。
- Dom操作是由 javaScript 實現的。
- 瀏覽器對于DOM操作的響應,是同步的。
基于這兩點,大家想想這種業務場景:
// 通過循環給li元素設置寬度 var lis = doucument.element.getTagName('li'); for(var i=1;i<10;1++){lis [i].style.width = i +'px' }在這個代碼中,可以知道,一個 li 的操作,是會引起瀏覽器的重排重繪的。
DOM是由 js 實現的,但 js 又是單線程。在這個代碼中,每一個li的操作改變,都被存儲在js內存當中。
也就是說,只有在等 js 代碼跑完了之后,瀏覽器才會開始響應這段代碼所帶來的 js 操作。這些操作扎堆在一起等來瀏覽器來響應。瀏覽器的響應又是同步的,所以它只能一次一次去執行重排計算,渲染,再計算,再渲染。。。
這樣,效率其實很低。重排,重新渲染的計算量完全取決于 DOM操作 的影響范圍??赡苓@時,你會想,瀏覽器就不能智能一點嗎?幾次操作一次計算,一次渲染不就好了?
嗯。。。也許瀏覽器有它自己的考慮。
重排(Relayout/Reflow)
這一部分,只是想讓更詳細的了解一下重排的意思。
想要了解重排,要先知道:瀏覽器渲染頁面默認采用的是流式布局模型;
所謂重排,實際上是根據渲染樹中每個渲染對象的信息,計算出各自渲染對象的幾何信息(DOM對象的位置和尺寸大小),并將其安置在界面中的正確位置。
從這個意思來看,某一個DOM節點信息更改了,就需要對DOM結構進行重新計算,重新布局界面,只是這個結構更改程度會決定周邊DOM更改范圍,即全局范圍和局部范圍。
全局范圍就是從根節點 html 開始對整個渲染樹進行重新布局,例如當我們改變了窗口尺寸或方向或者是修改了根元素的尺寸或者字體大小等;而局部布局可以是對渲染樹的某部分或某一個渲染對象進行重新布局。
重排一定會引起重繪。
在此,總結會引起重排的操作有:
重繪
相比重排,重繪就簡單多了,所謂重繪,就是當頁面中元素樣式的改變并不影響它在文檔流中的位置時,例如更改了字體顏色,瀏覽器會將新樣式賦予給元素并重新繪制的過程稱。
常見引起重繪的屬性優化方案
DOM操作的背后,隱藏這不止止是文中所描述的這些代價。為了給用戶更好的瀏覽體驗,可以有以下優化的方案:
- 減少DOM操作
如果在一個局部方法中需要多次訪問同一個dom,則先暫存它的引用 - 采用更高效的API或者更高效的寫法
1)用querySelectorAll()替代getElementByXX()。
2)開啟動畫的GPU加速,把渲染計算交給GPU
3)用事件委托來減少事件處理器的數量。
4)使用react、vue等頁面框架來編寫View頁面。react采用虛擬dom,盡可能的講多次重排濃縮成一次。 - 減少重排
- CSS及動畫處理
1)用更高效的css3效果,通過類名控制動畫,盡量避免直接操作DOM屬性;
2)在動畫的元素多嵌套一層div,盡量用絕對定位或者固定定位使其脫離文檔流,再進行動畫處理;
3)盡量在滾動的時候,停止動畫;
4)動畫實現的速度選擇。以1px移動最為平滑,但是reflow就會果與頻繁,建議以3px移動則會好很多。
總結
文中是自己通過學習,也有借鑒別人的知識點,希望能幫助你。
知識分享,若有錯誤的地方,請留言!
自我學習,自我勤勉,在未來感謝曾經努力的自己!
總結
以上是生活随笔為你收集整理的js hover 触发事件_为什么说JS的DOM操作很耗性能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java集合中中文排序_利用Collat
- 下一篇: RTX5 | 线程标志组02 - 获取线