您好,登錄后才能下訂單哦!
這篇文章主要介紹“Vue.js中怎么優(yōu)化性能”,在日常操作中,相信很多人在Vue.js中怎么優(yōu)化性能問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Vue.js中怎么優(yōu)化性能”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
01 Functional components
原理:****函數(shù)式組件**與普通組件相比,它沒(méi)有狀態(tài)(沒(méi)有響應(yīng)式數(shù)據(jù)),沒(méi)有實(shí)例 (沒(méi)有 this 上下文)。我們可以把函數(shù)式組件想像成組件里的一個(gè)函數(shù),入?yún)⑹卿秩旧舷挛模╮ender context),返回值是渲染好的 HTML。正是因?yàn)楹瘮?shù)式組件精簡(jiǎn)了很多例如響應(yīng)式和鉤子函數(shù)的處理,因此渲染性能會(huì)有一定提高。
適用場(chǎng)景:
不需要響應(yīng)式數(shù)據(jù)及處理邏輯的純展示組件
用來(lái)標(biāo)記或提供基本功能的高階組件
循環(huán)(v-for)中的元素
原理:**在優(yōu)化前的代碼中,每次 props 傳入的 number 發(fā)生變化時(shí)都會(huì)重新渲染,在渲染的過(guò)程中又會(huì)重新調(diào)用 heavy 函數(shù)進(jìn)行耗性能的運(yùn)算。而優(yōu)化后的代碼邏輯是將復(fù)雜運(yùn)算封裝在子組件內(nèi),由于 Vue 的更新是組件粒度的,當(dāng)傳入的 number 發(fā)生變化時(shí),父組件會(huì)重新渲染,而子組件由于并不依賴(lài) number 因此并不會(huì)重新渲染。執(zhí)行計(jì)算的次數(shù)少了,性能自然也提升了。
**另:**這里其實(shí)也可以用 computed 計(jì)算屬性來(lái)優(yōu)化(外部依賴(lài)沒(méi)有變化時(shí)不會(huì)重新計(jì)算,而且省去了額外渲染子組件的開(kāi)銷(xiāo))
原理:**對(duì)比前后代碼可以發(fā)現(xiàn)區(qū)別在于:優(yōu)化前的代碼在進(jìn)行計(jì)算時(shí)每次都直接引用 this.base,而優(yōu)化后的代碼將 this.base 使用局部變量 base 進(jìn)行了緩存,在之后的計(jì)算中都調(diào)用局部變量進(jìn)行計(jì)算。為什么會(huì)造成如此明顯的性能差異呢?原因在于每次訪(fǎng)問(wèn) this.base 時(shí),由于 this.base 是計(jì)算屬性,因此會(huì)執(zhí)行一段邏輯代碼查看已有的依賴(lài)項(xiàng)是否發(fā)生變化,如果發(fā)生變化則重新計(jì)算,沒(méi)有則返回上一次計(jì)算值。這類(lèi)計(jì)算邏輯的性能消耗在僅僅多調(diào)用幾次時(shí)可能還不明顯,但執(zhí)行多了(類(lèi)似示例每幀更新 300 個(gè)組件,每個(gè)組件在一次更新內(nèi)又調(diào)用了多次 this.base)則會(huì)有比較大的性能差異。
原理:
實(shí)現(xiàn)方式:v-if 是動(dòng)態(tài)的向 DOM 樹(shù)內(nèi)添加或者刪除 DOM 元素,v-show 是通過(guò)設(shè)置 DOM 元素的 display 樣式屬性控制顯隱。
編譯過(guò)程:v-if 切換有一個(gè)局部編譯卸載的過(guò)程,切換過(guò)程中合適地銷(xiāo)毀和重建內(nèi)部的事件監(jiān)聽(tīng)和子組件,v-show 只是簡(jiǎn)單的基于 CSS 切換。
編譯條件:v-if 是惰性的,如果初始條件為假,則什么也不做,只有在條件第一次變?yōu)檎鏁r(shí)才開(kāi)始局部編譯, v-show 是在任何條件下都被編譯,然后被緩存,而且 DOM 元素保留。
性能消耗:v-if 有更高的切換消耗,v-show 有更高的初始渲染消耗。
使用場(chǎng)景:v-if 適合條件不太可能改變的情況,v-show 適合條件頻繁切換的情況。
原理:**在非優(yōu)化場(chǎng)景下,我們每次點(diǎn)擊按鈕切換路由視圖,都會(huì)重新渲染一次組件,渲染組件就會(huì)經(jīng)過(guò)組件初始化,render、patch 等過(guò)程,如果組件比較復(fù)雜,或者嵌套較深,那么整個(gè)渲染耗時(shí)就會(huì)很長(zhǎng)。而在使用 KeepAlive 后,被 KeepAlive 包裹的組件在經(jīng)過(guò)第一次渲染后的 vnode 以及 DOM 都會(huì)被緩存起來(lái),然后再下一次再次渲染該組件的時(shí)候,直接從緩存中拿到對(duì)應(yīng)的 vnode 和 DOM,然后渲染,并不需要再走一次組件初始化,render 和 patch 等一系列流程,減少了 script 的執(zhí)行時(shí)間,性能更好。
但是使用 KeepAlive 組件并非沒(méi)有成本,因?yàn)樗鼤?huì)占用更多的內(nèi)存去做緩存,這是一種典型的空間換時(shí)間優(yōu)化思想的應(yīng)用。
其中 deferMixin 如下:
原理:**Defer 的主要思想就是把一個(gè)組件的一次渲染拆成多次,它內(nèi)部維護(hù)了 displayPriority 變量,然后在通過(guò) requestAnimationFrame 在每一幀渲染的時(shí)候自增,最多加到 count。然后使用 Defer mixin 的組件內(nèi)部就可以通過(guò) v-if="defer(xxx)" 的方式來(lái)控制在 displayPriority 增加到 xxx 的時(shí)候渲染某些區(qū)塊了。
當(dāng)你有渲染耗時(shí)的組件,使用 Deferred 做漸進(jìn)式渲染是不錯(cuò)的注意,它能避免一次 render 由于 JS 執(zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致渲染卡住的現(xiàn)象。
原理:**使用時(shí)間分片可以避免一次性提交的數(shù)據(jù)過(guò)多,內(nèi)部 Js 執(zhí)行時(shí)間過(guò)長(zhǎng),阻塞 UI 進(jìn)程導(dǎo)致頁(yè)面卡死。
另:**在執(zhí)行耗時(shí)任務(wù)處理時(shí),我們通常會(huì)加一個(gè) loading 效果,但通過(guò)優(yōu)化前后對(duì)比可以發(fā)現(xiàn):優(yōu)化前 JS 一直長(zhǎng)時(shí)間運(yùn)行,阻塞 UI 進(jìn)程,因此并不會(huì)展示 loading 動(dòng)畫(huà);優(yōu)化后由于將耗時(shí)任務(wù)拆成多個(gè)時(shí)間片提交,單次 JS 運(yùn)行時(shí)間變短了,loading 動(dòng)畫(huà)也有機(jī)會(huì)渲染了。
原理:**內(nèi)部提交數(shù)據(jù)時(shí)會(huì)默認(rèn)將新提交的數(shù)據(jù)定義成響應(yīng)式,如果對(duì)象的子屬性是對(duì)象,還會(huì)遞歸讓子屬性也變成響應(yīng)式。因此當(dāng)提交數(shù)據(jù)過(guò)多時(shí),整個(gè)過(guò)程十分耗時(shí)。而優(yōu)化后通過(guò)將 data 中的屬性標(biāo)志 configurable 手動(dòng)變成 false,這樣內(nèi)部通過(guò) Object.keys(obj) 獲取對(duì)象屬性數(shù)組會(huì)忽略 data,也就不會(huì)為 data 這個(gè)屬性 defineReactive,由于 data 指向的是一個(gè)對(duì)象,這樣也就會(huì)減少遞歸響應(yīng)式的邏輯,相當(dāng)于減少了這部分的性能損耗。數(shù)據(jù)量越大,這種優(yōu)化的效果就會(huì)更明顯。
設(shè)置 configurable 與直接使用 Object.freeze 的區(qū)別是:
**configurable: false**
的用途是防止更改和刪除屬性標(biāo)志,但是允許更改對(duì)象的值;
**Object.freeze(obj)**
禁止添加/刪除/更改屬性。為所有現(xiàn)有的屬性設(shè)置 configurable: false
, writable: false
。
// configurable: false let user = { name: "John" }; Object.defineProperty(user, "name", { configurable: false }); user.name = "Pete"; // 正常工作 delete user.name; // Error // Object.freeze(obj) let user = { name: "John" }; Object.freeze(user); user.name = "Pete"; console.log(user.name); // "John"復(fù)制代碼
原理:**虛擬滾動(dòng)的實(shí)現(xiàn)方式是僅渲染視圖范圍內(nèi)的 DOM,渲染內(nèi)容少時(shí)性能自然會(huì)好很多。虛擬滾動(dòng)組件也是 Guillaume Chau 寫(xiě)的,感興趣的同學(xué)可以去研究它的源碼實(shí)現(xiàn),基本原理就是監(jiān)聽(tīng)滾動(dòng)事件,動(dòng)態(tài)更新需要顯示的 DOM 元素,計(jì)算出它們?cè)谝晥D中的位移。虛擬滾動(dòng)組件也并非沒(méi)有成本,因?yàn)樗枰跐L動(dòng)的過(guò)程中實(shí)時(shí)去計(jì)算,所以會(huì)有一定的 script 執(zhí)行的成本。因此如果列表的數(shù)據(jù)量不是很大的情況,我們使用普通的滾動(dòng)就足夠了
到此,關(guān)于“Vue.js中怎么優(yōu)化性能”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。