Vue3-0 七大亮點是什麼??
作者:獵戶座小陳
juejin.cn/post/6967570296677236743
一,性能比 2.x 快 1.2~2 倍
diff 算法的優化
在 vue2 中,虛擬 dom 是全量比較的。
在 vue3 中,增加了靜態標記 PatchFlag。在創建 vnode 的時候,會根據 vnode 的內容是否可以變化,爲其添加靜態標記 PatchFlag。diff 的時候,只會比較有 PatchFlag 的節點。PatchFlag 是有類型的,比如一個可變化文本節點,會將其添加 PatchFlag 枚舉值爲 TEXT 的靜態標記。這樣在 diff 的時候,只需比對文本內容。需要比對的內容更少了。PatchFlag 還有動態 class、動態 style、動態屬性、動態 key 屬性等枚舉值。
render 階段的靜態提升(render 階段指生成虛擬 dom 樹的階段)
在 vue2 中,一旦檢查到數據變化,就會 re-render 組件,所有的 vnode 都會重新創建一遍,形成新的 vdom 樹。
在 vue3 中,對於不參與更新的 vnode,會做靜態提升,只會被創建一次,在 re-render 時直接複用。
靜態提升可以理解爲第一次 render 不參與更新的 vnode 節點的時候,保存它們的引用。re-render 新 vdom 樹時,直接拿它們的引用過來即可,無需重新創建。
事件偵聽緩存
在 vue2 中,我們寫的 @click="onClick" 也是被當作動態屬性,diff 的時候也要對比。但我們知道它不會變化,比如變成 @click="onClick2",綁定別的值。
在 vue3 中,如果事件是不會變化的,會將 onClick 緩存起來(跟靜態提升達到的效果類似),該節點也不會被標記上 PatchFlag(也就是無需更新的節點)。這樣在 render 和 diff 兩個階段,事件偵聽屬性都節約了不必要的性能消耗。
我曾經維護過一個擁有很龐大 dom 樹的頁面。由於節點非常多,無需參與更新的節點也很多,使用 vue2 的情況下,在 render 和 diff 兩個階段,消費了很多性能,如果當時有 vue3 的話,我想性能會被優化很多。
二,按需編譯,體積比 Vue2.x 更小(Tree shaking)
在 vue3 中,可以如下面這樣引用 vue 的功能函數,如果你的項目沒有用到 watch,那編譯時就會把 tree shaking 掉。
import { computed, watch, nextTick } from "vue";
複製代碼
利用的就是 ES6 模塊系統 import/export。
三,Compostion API: 組合 API / 注入 API
這裏要說到代碼的組織方式,傳統的網頁是 html/css/javascript(結構 / 樣式 / 邏輯)分離。vue/react 通過組件化的方式,將聯繫緊密的結構 / 樣式 / 邏輯放在一起,有利於代碼的維護。
compostion api 更進一步,着力於 JavaScript(邏輯)部分,將邏輯相關的代碼放在一起,近而有利於代碼的維護。
在 vue2 的組件內,使用的是 Option API 風格 (data/methods/mounted) 來組織的代碼,這樣會讓邏輯分散,舉個例子就是我們完成一個計數器功能,要在 data 裏聲明變量,在 methods 定義響應函數,在 mounted 裏初始化變量,如果在一個功能比較多、代碼量比較大的組件裏,你要維護這樣一個功能,就需要在 data/methods/mounted 反覆的切換到對應位置,然後進行代碼的更改。
在 vue3 中,使用 setup 函數。如下所示跟 count 相關的邏輯,都放到 counter.js 文件裏,跟 todo 相關的邏輯放到 todos.js 裏。
import useCounter from './counter'
import useTodo from './todos'
setup(){
let { val, todos, addTodo } = useTodo()
let {count,add} = useCounter()
return {
val, todos, addTodo,
count,add,
}
}
複製代碼
在我看來這就是 Compostion API 最大的特點,以功能爲單位的代碼組織方式。同時它可以讓代碼更易重用。
說到重用,Compostion API 的方式也比 mixin 的方式好很多,你可以清楚的看到組件使用的數據和方法來自哪個模塊,而 mixin 進組件的功能,常常會讓我們困惑此功能來自哪個 mixin。
四,更好的 TS 支持
vue2 不適合使用 ts,原因在於 vue2 的 Option API 風格。options 是個簡單對象,而 ts 是一種類型系統、面向對象的語法。兩者有點不匹配。
在 vue2 結合 ts 的具體實踐中,要用 vue-class-component 強化 vue 組件,讓 Script 支持 TypeScript 裝飾器,用 vue-property-decorator 來增加更多結合 Vue 特性的裝飾器,最終搞的 ts 的組件寫法和 js 的組件寫法差別挺大。
在 vue3 中,量身打造了 defineComponent 函數,使組件在 ts 下,更好的利用參數類型推斷 。Composition API 代碼風格中,比較有代表性的 api 就是 ref 和 reactive,也很好的支持了類型聲明。
import { defineComponent, ref } from 'vue'
const Component = defineComponent({
props: {
success: { type: String },
student: {
type: Object as PropType<Student>,
required: true
}
},
setup() {
const year = ref(2020)
const month = ref<string | number>('9')
month.value = 9 // OK
const result = year.value.split('') // => Property 'split' does not exist on type 'number'
}
複製代碼
五,自定義渲染 API(Custom Renderer API)
下面我們可以看到 vue2 和 vue3 的入口寫法有所不同
// vue2
import Vue from 'vue'
import App from './App.vue'
new Vue({ => h(App)}).$mount('#app')
// vue3
const { createApp } from 'vue'
import App from "./src/App"
createApp(App).mount(('#app')
複製代碼
vue 官方實現的 createApp 會給我們的 template 映射生成 html 代碼,但是要是你不想渲染生成到 html ,而是要渲染生成到 canvas 之類的不是 html 的代碼的時候,那就需要用到 Custom Renderer API 來定義自己的 render 渲染生成函數了。
// 你自己實現一個createApp,比如是渲染到canvas的。
import { createApp } from "./runtime-render";
import App from "./src/App"; // 根組件
createApp(App).mount('#app');
複製代碼
六,更先進的組件
Fragment 組件
// vue2 是不允許這樣寫的,組件必須有一個跟節點,現在可以這樣寫,vue 將爲我們創建一個虛擬的 Fragment 節點。
<template>
<div>Hello</div>
<div>World</div>
</template>
複製代碼
這樣寫有何好處呢?一是如果根節點不是必要的,無需創建了,減少了節點數。二是 Fragment 節點是虛擬的,不會 DOM 樹中呈現。
Suspense 組件
<Suspense>
<template >
<Suspended-component />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
複製代碼
在 Suspended-component 完全渲染之前,備用內容會被顯示出來。如果是異步組件,Suspense 可以等待組件被下載,或者在設置函數中執行一些異步操作。
七,更快的開發體驗(vite 開發構建工具)
在使用 webpack 作爲開發構建工具時,npm run dev 都要等一會,項目越大等的時間越長。熱重載頁有幾秒的延遲,但是如果用 vite 來做 vue3 的開發構建工具,npm run dev 秒開,熱重載也很快。這種開發體驗真是很爽,拒絕等待。
vite 的原理還是用了瀏覽器支持 import 關鍵字了,啓動項目不用 webpack 構建工具先構建了,瀏覽器直接請求路由對應的代碼文件,代理服務器針對單個文件進行編譯並返回。如果請求的文件裏還 import 了其他文件,同理瀏覽器繼續發請求,代理服務器返回。就這樣實現了 npm run dev 時無需編譯,實時請求實時編譯。
總結:
其他的,數據監聽方式變成了 Proxy,消除了 Object.defineProperty 現有的限制(例如無法檢測新的屬性添加),並提供更好的性能。
vue3 解決了 vue2 的一些問題,大型應用的性能問題、ts 支持不友好問題,自定義渲染 API 解決體系架構存在的問題,如果在 vue3 的基礎上實現 weex 框架會好很多。也做出了很多優化,Compostion API 讓代碼的組織形式更好。vite 開發構建工具讓開發體驗更好,Tree shaking 讓包更小、性能更優。
總的來說 vue3 還是非常棒的,帶來了很多非常好的新特性。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/p2k7rRCMlqvUr4u2xaeeaw