日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

php 频繁dom和 文件,性能优化之为什么不要频繁操作DOM

發(fā)布時(shí)間:2023/12/20 php 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php 频繁dom和 文件,性能优化之为什么不要频繁操作DOM 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

性能優(yōu)化:為什么不要頻繁操作DOM

@[toc]

性能優(yōu)化的時(shí)候,我們常說“不要頻繁操作DOM”,但是“DOM 為什么這么慢”以及“如何使 DOM 變快”呢。

DOM 為什么這么慢,因?yàn)?#xff0c;DOM和JS的跨界交流

把 DOM 和 JavaScript 各自想象成一個(gè)島嶼,它們之間用收費(fèi)橋梁連接。——《高性能 JavaScript》

JS 是很快的,在 JS 中修改 DOM 對(duì)象也是很快的。在JS的世界里,一切是簡單的、迅速的。但 DOM 操作并非 JS 一個(gè)人的獨(dú)舞,而是兩個(gè)模塊之間的協(xié)作。

JS 引擎和渲染引擎(瀏覽器內(nèi)核)是獨(dú)立實(shí)現(xiàn)的。當(dāng)我們用 JS 去操作 DOM 時(shí),本質(zhì)上是 JS 引擎和渲染引擎之間進(jìn)行了“跨界交流”。

“跨界交流”要收費(fèi)——這個(gè)開銷本身就是不可忽略的。我們每操作一次 DOM(不管是為了修改還是僅僅為了訪問其值),都要跨界一次。跨界的次數(shù)一多,就會(huì)產(chǎn)生比較明顯的性能問題。因此“減少 DOM 操作”的建議,并非空穴來風(fēng)。

對(duì) DOM 的修改引發(fā)樣式的更迭

很多時(shí)候,我們對(duì) DOM 的操作都不會(huì)局限于訪問,而是為了修改它。當(dāng)我們對(duì) DOM 的修改會(huì)引發(fā)它外觀(樣式)上的改變時(shí),就會(huì)觸發(fā)回流或重繪。

這個(gè)過程本質(zhì)上還是因?yàn)槲覀儗?duì) DOM 的修改觸發(fā)了渲染樹(Render Tree)的變化所導(dǎo)致的:

回流:當(dāng)我們對(duì) DOM 的修改引發(fā)了 DOM 幾何尺寸變化(比如修改元素的寬、高或隱藏元素等)時(shí),瀏覽器需要重新計(jì)算元素的幾何屬性(其他元素的幾何屬性和位置也會(huì)因此受到影響),然后再將計(jì)算的結(jié)果繪制出來。這個(gè)過程就是回流(也叫重排)。

重繪:當(dāng)我們對(duì) DOM 的修改導(dǎo)致了樣式的變化、卻并未影響其幾何屬性(比如修改了顏色或背景色)時(shí),瀏覽器不需重新計(jì)算元素的幾何屬性、直接為該元素繪制新的樣式(跳過了上圖所示的回流環(huán)節(jié))。這個(gè)過程叫做重繪。

由此我們可以看出,重繪不一定導(dǎo)致回流,回流一定會(huì)導(dǎo)致重繪。硬要比較的話,回流比重繪做的事情更多,帶來的開銷也更大。但這兩個(gè)說到底都是吃性能的,所以都不是什么善茬。我們?cè)陂_發(fā)中,要從代碼層面出發(fā),盡可能把回流和重繪的次數(shù)最小化。

如何使DOM變快

知道了 DOM 慢的原因,我們就可以對(duì)癥下藥了。

減少 DOM 操作:少“跨界交流”

例子,HTML 內(nèi)容如下:

DOM操作測(cè)試

此時(shí)我有一個(gè)假需求——我想往 container 元素里寫 10000 句一樣的話。如果我這么做:

for(var count=0;count<10000;count++){

document.getElementById('container').innerHTML+='我是一個(gè)小測(cè)試'

}

這段代碼有兩個(gè)明顯的可優(yōu)化點(diǎn)。

第一點(diǎn),跨界交流太多了。我們每一次循環(huán)都調(diào)用 DOM 接口重新獲取了一次 container 元素,相當(dāng)于每次循環(huán)都進(jìn)行一次“跨界交流”。前后交了 10000 次,但其中 9999 次都可以用緩存變量的方式節(jié)省下來:

// 只獲取一次container

let container = document.getElementById('container')

for(let count=0;count<10000;count++){

container.innerHTML += '我是一個(gè)小測(cè)試'

}

第二點(diǎn),不必要的 DOM 更改太多了。我們的 10000 次循環(huán)里,修改了 10000 次 DOM 樹。我們前面說過,對(duì) DOM 的修改會(huì)引發(fā)渲染樹的改變、進(jìn)而去走一個(gè)(可能的)回流或重繪的過程,而這個(gè)過程的開銷是很“貴”的。這么貴的操作,我們竟然重復(fù)執(zhí)行了 N 多次!其實(shí)我們可以通過就事論事的方式節(jié)省下來不必要的渲染:

let container = document.getElementById('container')

let content = ''

for(let count=0;count<10000;count++){

// 先對(duì)內(nèi)容進(jìn)行操作

content += '我是一個(gè)小測(cè)試'

}

// 內(nèi)容處理好了,最后再觸發(fā)DOM的更改

container.innerHTML = content

JS 層面的事情,JS 自己去處理,處理好了,再來找 DOM 打報(bào)告。

事實(shí)上,考慮JS 的運(yùn)行速度,比 DOM 快得多這個(gè)特性。我們減少 DOM 操作的核心思路,就是讓 JS 去給 DOM 分壓。

這個(gè)思路,在 DOM Fragment 中體現(xiàn)得淋漓盡致。

DocumentFragment 接口表示一個(gè)沒有父級(jí)文件的最小文檔對(duì)象。它被當(dāng)做一個(gè)輕量版的 Document 使用,用于存儲(chǔ)已排好版的或尚未打理好格式的XML片段。因?yàn)?DocumentFragment 不是真實(shí) DOM 樹的一部分,它的變化不會(huì)引起 DOM 樹的重新渲染的操作(reflow),且不會(huì)導(dǎo)致性能等問題。

在我們上面的例子里,字符串變量 content 就扮演著一個(gè) DOM Fragment 的角色。其實(shí)無論字符串變量也好,DOM Fragment 也罷,它們本質(zhì)上都作為脫離了真實(shí) DOM 樹的容器出現(xiàn),用于緩存批量化的 DOM 操作。

前面我們直接用 innerHTML 去拼接目標(biāo)內(nèi)容,這樣做固然有用,但卻不夠優(yōu)雅。相比之下,DOM Fragment 可以幫助我們用更加結(jié)構(gòu)化的方式去達(dá)成同樣的目的,從而在維持性能的同時(shí),保住我們代碼的可拓展和可維護(hù)性。我們現(xiàn)在用 DOM Fragment 來改寫上面的例子:

let container = document.getElementById('container')

// 創(chuàng)建一個(gè)DOM Fragment對(duì)象作為容器

let content = document.createDocumentFragment()

for(let count=0;count<10000;count++){

// span此時(shí)可以通過DOM API去創(chuàng)建

let oSpan = document.createElement("span")

oSpan.innerHTML = '我是一個(gè)小測(cè)試'

// 像操作真實(shí)DOM一樣操作DOM Fragment對(duì)象

content.appendChild(oSpan)

}

// 內(nèi)容處理好了,最后再觸發(fā)真實(shí)DOM的更改

container.appendChild(content)

我們運(yùn)行這段代碼,可以得到與前面兩種寫法相同的運(yùn)行結(jié)果。

可以看出,DOM Fragment 對(duì)象允許我們像操作真實(shí) DOM 一樣去調(diào)用各種各樣的 DOM API,我們的代碼質(zhì)量因此得到了保證。

總結(jié)

以上是生活随笔為你收集整理的php 频繁dom和 文件,性能优化之为什么不要频繁操作DOM的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。