您好,登錄后才能下訂單哦!
小編給大家分享一下Dom節(jié)點(diǎn)怎么進(jìn)行優(yōu)化,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
DOM操作對(duì)性能影響最大是因?yàn)樗鼘?dǎo)致了瀏覽器的重繪和回流,我們都知道頁面UI的更改都是通過DOM操作實(shí)現(xiàn)的,DOM雖然提供了許多api方便我們操作dom,但DOM操作的代價(jià)很高,頁面前端代碼的性能瓶頸也大多集中在DOM操作上,所以前端性能優(yōu)化的一個(gè)主要的關(guān)注點(diǎn)就是DOM操作的優(yōu)化。
瀏覽器渲染機(jī)制:
瀏覽器渲染頁面
瀏覽器解析 HTML 文檔的源碼,然后構(gòu)造出一個(gè) DOM 樹,遇到樣式就異步計(jì)算。
異步計(jì)算好的樣式與dom樹合成,構(gòu)建 render 樹。
進(jìn)行布局(layout) render 樹。
進(jìn)行繪制(painting) render 樹。
DOM樹與render樹的區(qū)別在于:樣式為display:none;的節(jié)點(diǎn)會(huì)在DOM樹中而不在渲染樹中。瀏覽器繪制了之后便開始解析js文件,根據(jù)js來確定是否重繪和重排。
頁面更改發(fā)生的操作:
回流:瀏覽器引擎發(fā)現(xiàn)render樹某個(gè)節(jié)點(diǎn)發(fā)生了變化影響了布局,需要倒回去重新渲染,我們稱這個(gè)回退的過程叫 回流。回流會(huì)從這個(gè)root frame開始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置。
重繪:改變某個(gè)元素的背景色、文字顏色、邊框顏色等等不影響頁面dom布局的操作。
js是單線程的,重繪和重排會(huì)阻塞用戶的操作以及影響網(wǎng)頁的性能
1、改變dom多個(gè)樣式,使用class,而非style,減少多次觸發(fā)回流重繪
舉例:改變dom元素寬高
var dom = document.getElementById('box') dom.style.width = '300px' dom.style.height = '300px'//訪問了三次dom,觸發(fā)了兩次回流和兩次重繪
優(yōu)化后:
.change { width: 300px; height: 300px; } document.getElementById('p').className = 'change'//只觸發(fā)一次
2、列表類型批量修改,脫離文檔流再恢復(fù),利用樣式為display:none;的節(jié)點(diǎn)會(huì)在DOM樹中而不在渲染樹中不會(huì)引起重繪回流。
如果要在一個(gè)dom集合中,給每個(gè)dom子節(jié)點(diǎn)加一個(gè)class,我們可以遍歷給每一個(gè)節(jié)點(diǎn)都加上class,這樣就觸發(fā)了多次的重繪和回流
/* //需要加入的樣式 .change { width: 300px; height: 300px; } */ var ul = document.getElementsByTagName('ul') var lis = document.getElementsByTagName('li') ul.style.display = 'none' for(var i = 0; i < lis.length; i++) { lis[i].className = 'change'; } ul.style.display = 'block'
3、DocumentFragment
虛擬DOM其實(shí)就是一個(gè)對(duì)象,js提供了reateDocumentFragment()方法用于創(chuàng)建一個(gè)空的虛擬節(jié)點(diǎn)對(duì)象,DocumentFragment節(jié)點(diǎn)不屬于文檔樹,當(dāng)需要添加多個(gè)dom元素時(shí),如果先將這些元素添加到DocumentFragment中,然后再將DocumentFragment對(duì)象添加到渲染樹上,會(huì)減少頁面渲染dom的次數(shù),效率會(huì)明顯提升。
var frag = document.createDocumentFragment() //創(chuàng)建一個(gè)虛擬節(jié)點(diǎn)對(duì)象 for(var i = 0; i < 10; i++) { var li = document.createElement("li") li.innerHTML = '我是第' + i + 1 + '個(gè)元素' frag.appendChild(li) //將li元素加到虛擬節(jié)點(diǎn)對(duì)象上 } ul.appendChild(frag) //將虛擬節(jié)點(diǎn)對(duì)象加到ul上
其它
1、事件委托,利用瀏覽器事件,冒泡捕獲減少頁面事件綁定,我們可以指定一個(gè)事件處理程序就可以管理某一類型的所有事件。事件函數(shù)過多會(huì)占用大量內(nèi)存,而且綁定事件的DOM元素越多會(huì)增加訪問dom的次數(shù),對(duì)頁面的交互就緒時(shí)間也會(huì)有延遲。
// 事件委托前 var lis = document.getElementsByTagName('li') for(var i = 0; i < lis.length; i++) { lis[i].onclick = function() { console.log(this.innerHTML) }} // 利用瀏覽器事件通過父元素委托事件給子元素 var ul = document.getElementsByTagName('ul')ul.onclick = function(event) { //也可以做判斷給指定的子元素綁定事件 console.log(event.target.innerHTML)};
2、在循環(huán)中的優(yōu)化減少操作dom次數(shù)
//例子1:減少在計(jì)算過程中操作dom // 優(yōu)化前,訪問了好多次dom,這些都是細(xì)節(jié)問題,有經(jīng)驗(yàn)的繞過,小白平常多注意就行 for(var i = 0; i < 10; i++) { document.getElementById('el').innerHTML += '1'} // 優(yōu)化后 var str = ''for(var i = 0; i < 10; i++) { str += '1'}document.getElementById('el').innerHTML = str/
這樣看獲取你體驗(yàn)不到緩存節(jié)點(diǎn)長度的作用,請(qǐng)看下面的例子
//不緩存 var ps = document.getElementsByTagName("p"), i, p; for( i=0; i<ps.length; i++ ){ p = document.createElement("p"); document.body.appendChild("p"); }造成死循環(huán),每次執(zhí)行for循環(huán)都會(huì)動(dòng)態(tài)獲取ps的長度,而我們每次進(jìn)入循環(huán)都增加了一個(gè)DOM(p),ps的長度也+1. //緩存 var ps = document.getElementsByTagName("p"), i, p,len; for( i=0;len=ps.length;i<len; i++ ){ p = document.createElement("p"); document.body.appendChild("p"); }//使用變量保存ps的長度。
3、選擇器區(qū)別
獲取元素最常見的有兩種方法,getElementsByXXX()和queryselectorAll(),這兩種選擇器區(qū)別是很大的,前者是獲取動(dòng)態(tài)集合,后者是獲取靜態(tài)集合
// 假設(shè)一開始有2個(gè)livar lis = document.getElementsByTagName('li') // 動(dòng)態(tài)集合 var ul = document.getElementsByTagName('ul')[0] for(var i = 0; i < 3; i++) { console.log(lis.length) var newLi = document.createElement('li') ul.appendChild(newLi)}// 輸出結(jié)果:2, 3, 4 // 優(yōu)化后 var lis = document.querySelectorAll('li') // 靜態(tài)集合 var ul = document.getElementsByTagName('ul')[0] for(var i = 0; i < 3; i++) { console.log(lis.length) var newLi = document.createElement('li') ul.appendChild(newLi)}// 輸出結(jié)果:2, 2, 2
對(duì)靜態(tài)集合的操作不會(huì)引起對(duì)文檔的重新查詢,相比于動(dòng)態(tài)集合更加優(yōu)化。
以上是“Dom節(jié)點(diǎn)怎么進(jìn)行優(yōu)化”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。