DOM優(yōu)化

1.節(jié)點(diǎn)修改

使用cloneNode在外部更新節(jié)點(diǎn)然后再通過(guò)replace與原始節(jié)點(diǎn)互換卸奉。

window.onload = function () {
        var orij = document.getElementById('content');
        //新的內(nèi)容替換原有的內(nèi)容
        var clone = orij.cloneNode(false);
        //在原有內(nèi)容的基礎(chǔ)上進(jìn)行修改
        //var clone = orij.cloneNode(true);
        var list = ['foo','bar','baz'];
        var content;
        for(var i = 0; i < list.length; i++){
            content = document.createTextNode(list[i]);
            clone.appendChild(content);
        }
        orij.parentNode.replaceChild(clone,orij);
    }

2.節(jié)點(diǎn)的添加

多個(gè)節(jié)點(diǎn)插入操作钝诚,即使在外面設(shè)置節(jié)點(diǎn)的元素和風(fēng)格再插入,由于多個(gè)節(jié)點(diǎn)還是會(huì)引發(fā)多次reflow择卦。
優(yōu)化的方法是創(chuàng)建DocumentFragment敲长,在其中插入節(jié)點(diǎn)后再添加到頁(yè)面。

 var btn = document.getElementById('btn');
        btn.onclick = function () {
            var list = document.getElementById('list');
            var fragment = document.createDocumentFragment();
            for(var i = 0; i < 5 ; i ++){
                var li = document.createElement('li');
                li.textContent = i;
                fragment.appendChild(li)
            }
            list.appendChild(fragment);
        }

3.CSS樣式轉(zhuǎn)換

如果需要?jiǎng)討B(tài)更改CSS樣式秉继,盡量采用觸發(fā)reflow次數(shù)較少的方式祈噪。
可以通過(guò)直接設(shè)置元素的className直接設(shè)置,只會(huì)觸發(fā)一次reflow尚辑。

//css
.content{
            width:200px;;
            height:200px;
            background-color: aqua;
        }
        .container{
            background-color: pink;
            width:200px;
            height: 200px;
        }

//HTML
<div class="content" id="content"></div>

//js
document.getElementById('content').className = "container";

4.減少DOM元素?cái)?shù)量

在控制臺(tái)的console中輸入下面的語(yǔ)句查看DOM元素?cái)?shù)量:

document.getElementsByTagName( '*' ).length

正常頁(yè)面的DOM元素?cái)?shù)量一般不應(yīng)該超過(guò)1000辑鲤。
DOM元素過(guò)多會(huì)使DOM元素查詢效率,樣式表匹配效率降低杠茬,是頁(yè)面性能最主要的瓶頸之一月褥。

5.DOM操作

  • DOM操作性能問(wèn)題主要有以下原因:

    • DOM元素過(guò)多導(dǎo)致元素定位緩慢弛随。
    • 大量的DOM接口調(diào)用。
    • Javascript和DOM之間的交互需要通過(guò)函數(shù)API接口來(lái)完成宁赤,造成延時(shí)舀透,尤其是在循環(huán)語(yǔ)句中。
    • DOM操作觸發(fā)頻繁的reflow(layout)和repaint决左。
    • layout發(fā)生在repaint之前愕够,所以layout相對(duì)來(lái)說(shuō)會(huì)造成更多性能損耗。
      • reflow(layout)就是計(jì)算頁(yè)面元素的幾何信息佛猛。
      • repaint就是繪制頁(yè)面元素惑芭。
    • 對(duì)DOM進(jìn)行操作會(huì)導(dǎo)致瀏覽器執(zhí)行回流reflow。
  • 解決方法:

    • 純JAVASCRIPT執(zhí)行時(shí)間是很短的继找。
    • 最小化DOM訪問(wèn)次數(shù)遂跟,盡可能在js端執(zhí)行。
    • 如果需要多次訪問(wèn)某個(gè)DOM節(jié)點(diǎn)婴渡,請(qǐng)使用局部變量存儲(chǔ)對(duì)它的引用幻锁。
    • 謹(jǐn)慎處理HTML集合(HTML集合實(shí)時(shí)連系底層文檔),把集合的長(zhǎng) 度緩存到一個(gè)變量中边臼,并在迭代中使用它越败,如果需要經(jīng)常操作集合,建議把它拷貝到一個(gè)數(shù)組中硼瓣。
    • 如果可能的話,使用速度更快的API置谦,比如querySelectorAll和firstElementChild堂鲤。
    • 要留意重繪和重排。
    • 批量修改樣式時(shí)媒峡,離線操作DOM樹瘟栖。
    • 使用緩存,并減少訪問(wèn)布局的次數(shù)谅阿。
    • 動(dòng)畫中使用絕對(duì)定位半哟,使用拖放代理。
    • 使用事件委托來(lái)減少事件處理器的數(shù)量签餐。

事件委托示例

//HTML
<ul id="list">
    <li id="go">go something</li>
    <li id="do">do something</li>
    <li id="sayhi">say hi</li>
</ul>

//JS
var list = document.getElementById('list');
            list.addEventListener('click',function (event) {
                switch(event.target.id){
                    case 'go':
                        alert('aaa');
                        break;
                    case 'do':
                        document.title = 'I change document title';
                        break;
                    case 'sayhi':
                        location.href = 'http://www.reibang.com/p/91cb28114c82';
                        break;
                }
            })

5.DOM交互

在JAVASCRIPT中寓涨,DOM操作和交互要消耗大量時(shí)間,因?yàn)樗鼈兺枰匦落秩菊麄€(gè)頁(yè)面或者某一個(gè)部分氯檐。

  • 最小化現(xiàn)場(chǎng)更新
    當(dāng)需要訪問(wèn)的DOM部分已經(jīng)被渲染為頁(yè)面中的一部分戒良,那么DOM操作和交互的過(guò)程就是再進(jìn)行一次現(xiàn)場(chǎng)更新。

    • 現(xiàn)場(chǎng)更新是需要針對(duì)現(xiàn)場(chǎng)(相關(guān)顯示頁(yè)面的部分結(jié)構(gòu))立即進(jìn)行更新冠摄,每一個(gè)更改(不管是插入單個(gè)字符還是移除整個(gè)片段)糯崎,都有一個(gè)性能損耗几缭。
    • 現(xiàn)場(chǎng)更新進(jìn)行的越多,代碼完成執(zhí)行所花的時(shí)間也越長(zhǎng)沃呢。
  • 多使用innerHTML
    有兩種在頁(yè)面上創(chuàng)建DOM節(jié)點(diǎn)的方法:

    • 使用諸如createElement()和appendChild()之類的DOM方法年栓。
    • 使用innerHTML。
      • 當(dāng)使用innerHTML設(shè)置為某個(gè)值時(shí)薄霜,后臺(tái)會(huì)創(chuàng)建一個(gè)HTML解釋器某抓,然后使用內(nèi)部的DOM調(diào)用來(lái)創(chuàng)建DOM結(jié)構(gòu),而非基于Javascript的DOM調(diào)用黄锤。由于內(nèi)部方法是編譯好的而非解釋執(zhí)行搪缨,故執(zhí)行的更快。

對(duì)于小的DOM更改鸵熟,兩者效率差不多副编,但對(duì)于大的DOM更改,innerHTML要比標(biāo)準(zhǔn)的DOM方法創(chuàng)建同樣的DOM結(jié)構(gòu)快得多流强。

6.回流reflow

  • 發(fā)生場(chǎng)景痹届。
    • 改變窗體大小。
    • 更改字體打月。
    • 添加移除stylesheet塊队腐。
    • 內(nèi)容改變哪怕是輸入框輸入文字。
    • CSS虛類被觸發(fā)如 :hover奏篙。
    • 更改元素的className柴淘。
    • 當(dāng)對(duì)DOM節(jié)點(diǎn)執(zhí)行新增或者刪除操作或內(nèi)容更改時(shí)。
    • 動(dòng)態(tài)設(shè)置一個(gè)style樣式時(shí)(比如element.style.width="10px")秘通。
    • 當(dāng)獲取一個(gè)必須經(jīng)過(guò)計(jì)算的尺寸值時(shí)为严,比如訪問(wèn)offsetWidth、clientHeight或者其他需要經(jīng)過(guò)計(jì)算的CSS值肺稀。
  • 解決問(wèn)題的關(guān)鍵第股,就是限制通過(guò)DOM操作所引發(fā)回流的次數(shù)。
    • 在對(duì)當(dāng)前DOM進(jìn)行操作之前话原,盡可能多的做一些準(zhǔn)備工作夕吻,保證N次創(chuàng)建,1次寫入繁仁。
    • 在對(duì)DOM操作之前涉馅,把要操作的元素,先從當(dāng)前DOM結(jié)構(gòu)中刪除:
      • 通過(guò)removeChild()或者replaceChild()實(shí)現(xiàn)真正意義上的刪除黄虱。
      • 設(shè)置該元素的display樣式為“none”控漠。
    • 每次修改元素的style屬性都會(huì)觸發(fā)回流操作。
      • element.style.backgroundColor = "blue";
      • 使用更改className的方式替換style.xxx=xxx的方式。
      • 使用style.cssText = '';一次寫入樣式盐捷。
      • 避免設(shè)置過(guò)多的行內(nèi)樣式偶翅。
      • 添加的結(jié)構(gòu)外元素盡量設(shè)置它們的位置為fixed或absolute。
      • 避免使用表格來(lái)布局碉渡。
      • 避免在CSS中使用JavaScript expressions(IE only)聚谁。
    • 將獲取的DOM數(shù)據(jù)緩存起來(lái)。這種方法滞诺,對(duì)獲取那些會(huì)觸發(fā)回流操作的屬性(比如offsetWidth等)尤為重要形导。
    • 當(dāng)對(duì)HTMLCollection對(duì)象進(jìn)行操作時(shí),應(yīng)該將訪問(wèn)的次數(shù)盡可能的降至最低习霹,最簡(jiǎn)單的朵耕,你可以將length屬性緩存在一個(gè)本地變量中,這樣就能大幅度的提高循環(huán)的效率淋叶。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阎曹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子煞檩,更是在濱河造成了極大的恐慌处嫌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斟湃,死亡現(xiàn)場(chǎng)離奇詭異熏迹,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)凝赛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門注暗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人墓猎,你說(shuō)我怎么就攤上這事友存。” “怎么了陶衅?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)直晨。 經(jīng)常有香客問(wèn)我搀军,道長(zhǎng),這世上最難降的妖魔是什么勇皇? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任罩句,我火速辦了婚禮,結(jié)果婚禮上敛摘,老公的妹妹穿的比我還像新娘门烂。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布屯远。 她就那樣靜靜地躺著蔓姚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慨丐。 梳的紋絲不亂的頭發(fā)上坡脐,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音房揭,去河邊找鬼备闲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛捅暴,可吹牛的內(nèi)容都是我干的恬砂。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼蓬痒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼泻骤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起乳幸,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瞪讼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后粹断,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體符欠,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仅胞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年坠非,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忧吟。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡养筒,死狀恐怖曾撤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晕粪,我是刑警寧澤挤悉,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站巫湘,受9級(jí)特大地震影響装悲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尚氛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一诀诊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阅嘶,春花似錦属瓣、人聲如沸载迄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)护昧。三九已至,卻和暖如春溜畅,著一層夾襖步出監(jiān)牢的瞬間捏卓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工慈格, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怠晴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓浴捆,卻偏偏與公主長(zhǎng)得像蒜田,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子选泻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • AJax 優(yōu)化 緩存 Ajax 請(qǐng)求盡量使用GET, 僅取決于cookie數(shù)量 Cookie 優(yōu)化 減少Cooki...
    KeKeMars閱讀 9,347評(píng)論 5 89
  • DOM 一冲粤,DOM學(xué)習(xí)資源 MDN 、DOM specifications 二页眯、學(xué)習(xí)方法 看別人封裝的代碼 方...
    從前慢pearl閱讀 379評(píng)論 0 0
  • 問(wèn)答題47 /72 常見瀏覽器兼容性問(wèn)題與解決方案梯捕? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,737評(píng)論 1 92
  • 轉(zhuǎn)載說(shuō)明 一、介紹 瀏覽器可以被認(rèn)為是使用最廣泛的軟件窝撵,本文將介紹瀏覽器的工作原理傀顾,我們將看到,從你在地址欄輸入g...
    17碎那年閱讀 2,442評(píng)論 0 22
  • “這不就是一團(tuán)亂麻嗎碌奉!”“一灘爛泥短曾!”“復(fù)制粘貼而已,我也會(huì)赐劣〖倒眨”………… 以上對(duì)于現(xiàn)代藝術(shù)的評(píng)價(jià),相信大家都聽過(guò)魁兼,...
    點(diǎn)融黑幫閱讀 990評(píng)論 1 14