Vue.js中如何優化效能?9個小技巧分享

2022-04-12 22:00:07
Vue.js中如何優化效能?下面本篇文章給大家分享 效能優化的九個小技巧,希望對大家有所幫助!

(學習視訊分享:)

01 Functional components

1.png

1-2.png

**原理:****函數式元件**與普通元件相比,它沒有狀態(沒有響應式資料),沒有範例 (沒有 this 上下文)。我們可以把函數式元件想像成元件裡的一個函數,入參是渲染上下文(render context),返回值是渲染好的 HTML。正是因為函數式元件精簡了很多例如響應式和勾點函數的處理,因此渲染效能會有一定提高。

適用場景:

  1. 不需要響應式資料及處理邏輯的純展示元件

  2. 用來標記或提供基本功能的高階元件

  3. 迴圈(v-for)中的元素

02 Child component splitting

2.png

2-2.png

**原理:**在優化前的程式碼中,每次 props 傳入的 number 發生變化時都會重新渲染,在渲染的過程中又會重新呼叫 heavy 函數進行耗效能的運算。而優化後的程式碼邏輯是將複雜運算封裝在子元件內,由於 Vue 的更新是元件粒度的,當傳入的 number 發生變化時,父元件會重新渲染,而子元件由於並不依賴 number 因此並不會重新渲染。執行計算的次數少了,效能自然也提升了。

**另:**這裡其實也可以用 computed 計算屬性來優化(外部依賴沒有變化時不會重新計算,而且省去了額外渲染子元件的開銷)

03 Local variables

3.png

3-2.png

**原理:**對比前後程式碼可以發現區別在於:優化前的程式碼在進行計算時每次都直接參照 this.base,而優化後的程式碼將 this.base 使用區域性變數 base 進行了快取,在之後的計算中都呼叫區域性變數進行計算。為什麼會造成如此明顯的效能差異呢?原因在於每次存取 this.base 時,由於 this.base 是計算屬性,因此會執行一段邏輯程式碼檢視已有的依賴項是否發生變化,如果發生變化則重新計算,沒有則返回上一次計算值。這類計算邏輯的效能消耗在僅僅多呼叫幾次時可能還不明顯,但執行多了(類似範例每幀更新 300 個元件,每個元件在一次更新內又呼叫了多次 this.base)則會有比較大的效能差異。

04 Reuse DOM with v-show

4.png

4-2.png

原理:

  • 實現方式:v-if 是動態的向 DOM 樹內新增或者刪除 DOM 元素,v-show 是通過設定 DOM 元素的 display 樣式屬性控制顯隱。

  • 編譯過程:v-if 切換有一個區域性編譯解除安裝的過程,切換過程中合適地銷燬和重建內部的事件監聽和子元件,v-show 只是簡單的基於 CSS 切換。

  • 編譯條件:v-if 是惰性的,如果初始條件為假,則什麼也不做,只有在條件第一次變為真時才開始區域性編譯, v-show 是在任何條件下都被編譯,然後被快取,而且 DOM 元素保留。

  • 效能消耗:v-if 有更高的切換消耗,v-show 有更高的初始渲染消耗。

  • 使用場景:v-if 適合條件不太可能改變的情況,v-show 適合條件頻繁切換的情況。

05 Keep-alive

5.png

5-2.png

5-3.png

**原理:**在非優化場景下,我們每次點選按鈕切換路由檢視,都會重新渲染一次元件,渲染元件就會經過元件初始化,render、patch 等過程,如果元件比較複雜,或者巢狀較深,那麼整個渲染耗時就會很長。而在使用 KeepAlive 後,被 KeepAlive 包裹的元件在經過第一次渲染後的 vnode 以及 DOM 都會被快取起來,然後再下一次再次渲染該元件的時候,直接從快取中拿到對應的 vnode 和 DOM,然後渲染,並不需要再走一次元件初始化,render 和 patch 等一系列流程,減少了 script 的執行時間,效能更好。

但是使用 KeepAlive 元件並非沒有成本,因為它會佔用更多的記憶體去做快取,這是一種典型的空間換時間優化思想的應用。

06 Deferred features

6.png

其中 deferMixin 如下:

6-2.png

6-3.png

6-4.png

**原理:**Defer 的主要思想就是把一個元件的一次渲染拆成多次,它內部維護了 displayPriority 變數,然後在通過 requestAnimationFrame 在每一幀渲染的時候自增,最多加到 count。然後使用 Defer mixin 的元件內部就可以通過 v-if="defer(xxx)" 的方式來控制在 displayPriority 增加到 xxx 的時候渲染某些區塊了。

當你有渲染耗時的元件,使用 Deferred 做漸進式渲染是不錯的注意,它能避免一次 render 由於 JS 執行時間過長導致渲染卡住的現象。

07 Time slicing

7.png

7-2.png

7-3.png

**原理:**使用時間分片可以避免一次性提交的資料過多,內部 Js 執行時間過長,阻塞 UI 程序導致頁面卡死。

**另:**在執行耗時任務處理時,我們通常會加一個 loading 效果,但通過優化前後對比可以發現:優化前 JS 一直長時間執行,阻塞 UI 程序,因此並不會展示 loading 動畫;優化後由於將耗時任務拆成多個時間片提交,單次 JS 執行時間變短了,loading 動畫也有機會渲染了。

08 Non-reactive data

8.png

8-2.png

8-3.png

**原理:**內部提交資料時會預設將新提交的資料定義成響應式,如果物件的子屬性是物件,還會遞迴讓子屬性也變成響應式。因此當提交資料過多時,整個過程十分耗時。而優化後通過將 data 中的屬性標誌 configurable 手動變成 false,這樣內部通過 Object.keys(obj) 獲取物件屬性陣列會忽略 data,也就不會為 data 這個屬性 defineReactive,由於 data 指向的是一個物件,這樣也就會減少遞迴響應式的邏輯,相當於減少了這部分的效能損耗。資料量越大,這種優化的效果就會更明顯。

設定 configurable 與直接使用 Object.freeze 的區別是:

**configurable: false**的用途是防止更改和刪除屬性標誌,但是允許更改物件的值;

**Object.freeze(obj)**禁止新增/刪除/更改屬性。為所有現有的屬性設定 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"複製程式碼

09 Virtual scrolling

9.png

**原理:**虛擬捲動的實現方式是僅渲染檢視範圍內的 DOM,渲染內容少時效能自然會好很多。虛擬捲動元件也是 Guillaume Chau 寫的,感興趣的同學可以去研究它的原始碼實現,基本原理就是監聽捲動事件,動態更新需要顯示的 DOM 元素,計算出它們在檢視中的位移。虛擬捲動元件也並非沒有成本,因為它需要在捲動的過程中實時去計算,所以會有一定的 script 執行的成本。因此如果列表的資料量不是很大的情況,我們使用普通的捲動就足夠了

本文轉載自:https://juejin.cn/post/7084809333740929061

(學習視訊分享:)

以上就是Vue.js中如何優化效能?9個小技巧分享的詳細內容,更多請關注TW511.COM其它相關文章!