Vue3.0版本強(qiáng)勢(shì)升級(jí)點(diǎn)特性詳解
一、Composition API: 組合API/注入API
Vue3.0在架構(gòu)上相比vue2.x做了升級(jí),性能上得到了很大的提升,Composition API的出現(xiàn),讓組件抽離、邏輯代碼復(fù)用更加靈活。
這里要說(shuō)到代碼的組織方式,傳統(tǒng)的網(wǎng)頁(yè)是html/css/javascript(結(jié)構(gòu)/樣式/邏輯)分離。vue/react通過(guò)組件化的方式,將聯(lián)系緊密的結(jié)構(gòu)/樣式/邏輯放在一起,有利于代碼的維護(hù)。
Composition api更進(jìn)一步,著力于JavaScript(邏輯)部分,將邏輯相關(guān)的代碼放在一起,近而有利于代碼的維護(hù)。
在vue2的組件內(nèi),使用的是Option API風(fēng)格(data/methods/mounted)來(lái)組織的代碼,這樣會(huì)讓邏輯分散,舉個(gè)例子就是我們完成一個(gè)計(jì)數(shù)器功能,要在data里聲明變量,在methods定義響應(yīng)函數(shù),在mounted里初始化變量,如果在一個(gè)功能比較多、代碼量比較大的組件里,你要維護(hù)這樣一個(gè)功能,就需要在data/methods/mounted反復(fù)的切換到對(duì)應(yīng)位置,然后進(jìn)行代碼的更改。
在vue3中,使用setup函數(shù)。如下所示跟count相關(guān)的邏輯,都放到counter.js文件里,跟todo相關(guān)的邏輯放到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,
}
}
在我看來(lái)這就是Composition API最大的特點(diǎn),以功能為單位的代碼組織方式。同時(shí)它可以讓代碼更易重用。
說(shuō)到重用,Composition API的方式也比mixin的方式好很多,你可以清楚的看到組件使用的數(shù)據(jù)和方法來(lái)自哪個(gè)模塊,而mixin進(jìn)組件的功能,常常會(huì)讓我們困惑此功能來(lái)自哪個(gè)mixin。
二、自定義渲染API(Custom Renderer API)
vue2.x架構(gòu)問(wèn)題
vue2.x最開(kāi)始支持運(yùn)行在瀏覽器中,渲染到瀏覽器的dom上,隨著vue的流行,出現(xiàn)了weex和myvue。
weex:移動(dòng)端跨平臺(tái)方案,需要渲染到移動(dòng)設(shè)備。weex被寫(xiě)在vue原項(xiàng)目里,缺點(diǎn)是這使vue原項(xiàng)目更大了,也不是通用解決方案。myvue:小程序上使用,需要渲染到小程序框架上。myvue是單獨(dú)fork一份源代碼進(jìn)行更改,缺點(diǎn)也非常明顯,myvue中vue的版本跟官方版本從fork的那一刻開(kāi)始,就要開(kāi)始不一致了。
vue2.x項(xiàng)目架構(gòu)對(duì)于這種渲染到不同平臺(tái)不太友好,vue3.0推出了自定義渲染API解決了該問(wèn)題。
下面我們先看vue2和vue3的入口寫(xiě)法有所不同:
// 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官方實(shí)現(xiàn)的 createApp 會(huì)給我們的 template 映射生成 html 代碼,但是要是你不想渲染生成到 html ,而是要渲染生成到 canvas 之類的不是html的代碼的時(shí)候,那就需要用到 Custom Renderer API 來(lái)定義自己的 render 渲染生成函數(shù)了。
// 你自己實(shí)現(xiàn)一個(gè)createApp,比如是渲染到canvas的。
import { createApp } from "./runtime-render";
import App from "./src/App"; // 根組件
createApp(App).mount('#app');
有了Custom Renderer API,如weex和myvue這類方案的問(wèn)題就得到了完美解決。只需重寫(xiě)createApp即可。
三、更先進(jìn)的組件
Fragment組件
vue2是不允許這樣寫(xiě)的,組件必須有一個(gè)跟節(jié)點(diǎn),現(xiàn)在可以這樣寫(xiě),vue將為我們創(chuàng)建一個(gè)虛擬的Fragment節(jié)點(diǎn)。
<template> <div>Hello</div> <div>World</div> </template>
這樣寫(xiě)有何好處呢?一是如果根節(jié)點(diǎn)不是必要的,無(wú)需創(chuàng)建了,減少了節(jié)點(diǎn)數(shù)。二是Fragment節(jié)點(diǎn)是虛擬的,不會(huì)DOM樹(shù)中呈現(xiàn)。
Suspense組件
<Suspense>
<template >
<Suspended-component />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
在Suspended-component完全渲染之前,備用內(nèi)容會(huì)被顯示出來(lái)。如果是異步組件,Suspense可以等待組件被下載,或者在設(shè)置函數(shù)中執(zhí)行一些異步操作。
四、更好的TS支持
vue2不適合使用ts,原因在于vue2的Option API風(fēng)格。options是個(gè)簡(jiǎn)單對(duì)象,而ts是一種類型系統(tǒng)、面向?qū)ο蟮恼Z(yǔ)法。兩者有點(diǎn)不匹配。
在vue2結(jié)合ts的具體實(shí)踐中,要用 vue-class-component 強(qiáng)化 vue 組件,讓 Script 支持 TypeScript 裝飾器,用 vue-property-decorator 來(lái)增加更多結(jié)合 Vue 特性的裝飾器,最終搞的ts的組件寫(xiě)法和js的組件寫(xiě)法差別挺大。
在vue3中,量身打造了defineComponent函數(shù),使組件在ts下,更好的利用參數(shù)類型推斷 。Composition API 代碼風(fēng)格中,比較有代表性的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'
});
五、更快的開(kāi)發(fā)體驗(yàn)(vite開(kāi)發(fā)構(gòu)建工具)
在使用webpack作為開(kāi)發(fā)構(gòu)建工具時(shí),npm run dev都要等一會(huì),項(xiàng)目越大等的時(shí)間越長(zhǎng)。熱重載頁(yè)有幾秒的延遲,但是如果用vite來(lái)做vue3的開(kāi)發(fā)構(gòu)建工具,npm run dev 秒開(kāi),熱重載也很快。這種開(kāi)發(fā)體驗(yàn)真是很爽,拒絕等待。
vite的原理還是用了瀏覽器支持import關(guān)鍵字了,啟動(dòng)項(xiàng)目不用webpack構(gòu)建工具先構(gòu)建了,瀏覽器直接請(qǐng)求路由對(duì)應(yīng)的代碼文件,代理服務(wù)器針對(duì)單個(gè)文件進(jìn)行編譯并返回。如果請(qǐng)求的文件里還import了其他文件,同理瀏覽器繼續(xù)發(fā)請(qǐng)求,代理服務(wù)器返回。就這樣實(shí)現(xiàn)了npm run dev時(shí)無(wú)需編譯,實(shí)時(shí)請(qǐng)求實(shí)時(shí)編譯。
六、按需編譯,體積比Vue2.x更?。═ree shaking)
在vue3中,可以如下面這樣引用vue的功能函數(shù),如果你的項(xiàng)目沒(méi)有用到watch,那編譯時(shí)就會(huì)把tree shaking掉。
import { computed, watch, nextTick } from "vue";利用的就是 ES6 模塊系統(tǒng)import/export。
七、性能比2.x快1.2~2倍
diff算法的優(yōu)化
在vue2中,虛擬dom是全量比較的。
在vue3中,增加了靜態(tài)標(biāo)記PatchFlag。在創(chuàng)建vnode的時(shí)候,會(huì)根據(jù)vnode的內(nèi)容是否可以變化,為其添加靜態(tài)標(biāo)記PatchFlag。diff的時(shí)候,只會(huì)比較有PatchFlag的節(jié)點(diǎn)。 PatchFlag是有類型的,比如一個(gè)可變化文本節(jié)點(diǎn),會(huì)將其添加PatchFlag枚舉值為T(mén)EXT的靜態(tài)標(biāo)記。這樣在diff的時(shí)候,只需比對(duì)文本內(nèi)容。需要比對(duì)的內(nèi)容更少了。PatchFlag還有動(dòng)態(tài)class、動(dòng)態(tài)style、動(dòng)態(tài)屬性、動(dòng)態(tài)key屬性等枚舉值。
render階段的靜態(tài)提升(render階段指生成虛擬dom樹(shù)的階段)
在vue2中,一旦檢查到數(shù)據(jù)變化,就會(huì)re-render組件,所有的vnode都會(huì)重新創(chuàng)建一遍,形成新的vdom樹(shù)。
在vue3中,對(duì)于不參與更新的vnode,會(huì)做靜態(tài)提升,只會(huì)被創(chuàng)建一次,在re-render時(shí)直接復(fù)用。
靜態(tài)提升可以理解為第一次render不參與更新的vnode節(jié)點(diǎn)的時(shí)候,保存它們的引用。re-render新vdom樹(shù)時(shí),直接拿它們的引用過(guò)來(lái)即可,無(wú)需重新創(chuàng)建。
事件偵聽(tīng)緩存
在vue2中,我們寫(xiě)的@click="onClick"也是被當(dāng)作動(dòng)態(tài)屬性,diff的時(shí)候也要對(duì)比。但我們知道它不會(huì)變化,比如變成@click="onClick2",綁定別的值。
在vue3中,如果事件是不會(huì)變化的,會(huì)將onClick緩存起來(lái)(跟靜態(tài)提升達(dá)到的效果類似),該節(jié)點(diǎn)也不會(huì)被標(biāo)記上PatchFlag(也就是無(wú)需更新的節(jié)點(diǎn))。這樣在render和diff兩個(gè)階段,事件偵聽(tīng)屬性都節(jié)約了不必要的性能消耗。
我曾經(jīng)維護(hù)過(guò)一個(gè)擁有很龐大dom樹(shù)的頁(yè)面。由于節(jié)點(diǎn)非常多,無(wú)需參與更新的節(jié)點(diǎn)也很多,使用vue2的情況下,在render和diff兩個(gè)階段,消費(fèi)了很多性能,如果當(dāng)時(shí)有vue3的話,我想性能會(huì)被優(yōu)化很多。
減少創(chuàng)建組件實(shí)例的開(kāi)銷
vue2.x每創(chuàng)建一個(gè)實(shí)例,在this上要暴露data、props、computed這些,都是靠Object.defineProperty去定義的。這部分操作還是挺費(fèi)時(shí)的。
vue3.0中基于Proxy,減少了創(chuàng)建組件實(shí)例的性能開(kāi)銷。
總結(jié):
- 其他的,數(shù)據(jù)監(jiān)聽(tīng)方式變成了
Proxy,消除了Object.defineProperty現(xiàn)有的限制(例如無(wú)法檢測(cè)新的屬性添加),并提供更好的性能。 vue3解決了vue2的一些問(wèn)題,大型應(yīng)用的性能問(wèn)題、ts支持不友好問(wèn)題,自定義渲染API解決體系架構(gòu)存在的問(wèn)題,如果在vue3的基礎(chǔ)上實(shí)現(xiàn)weex框架會(huì)好很多。也做出了很多優(yōu)化,Composition API讓代碼的組織形式更好。vite開(kāi)發(fā)構(gòu)建工具讓開(kāi)發(fā)體驗(yàn)更好,Tree shaking讓包更小、性能更優(yōu)。- 總的來(lái)說(shuō)vue3還是非常棒,非常強(qiáng)大,帶來(lái)了很多非常好的新特性。
以上就是Vue3.0版本強(qiáng)勢(shì)升級(jí)點(diǎn)特性詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue3.0版本升級(jí)特性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue-video-player實(shí)現(xiàn)實(shí)時(shí)視頻播放方式(監(jiān)控設(shè)備-rtmp流)
這篇文章主要介紹了vue-video-player實(shí)現(xiàn)實(shí)時(shí)視頻播放方式(監(jiān)控設(shè)備-rtmp流),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Vue watch響應(yīng)數(shù)據(jù)實(shí)現(xiàn)方法解析
這篇文章主要介紹了Vue watch響應(yīng)數(shù)據(jù)實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
vue實(shí)現(xiàn)多個(gè)元素或多個(gè)組件之間動(dòng)畫(huà)效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)多個(gè)元素或多個(gè)組件之間動(dòng)畫(huà)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
Vue?transition組件簡(jiǎn)單實(shí)現(xiàn)數(shù)字滾動(dòng)
這篇文章主要為大家介紹了Vue?transition組件簡(jiǎn)單實(shí)現(xiàn)數(shù)字滾動(dòng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
vue2+elementUI實(shí)現(xiàn)下拉樹(shù)形多選框效果實(shí)例
這篇文章主要給大家介紹了關(guān)于vue2+elementUI實(shí)現(xiàn)下拉樹(shù)形多選框效果的相關(guān)資料,這是最近的工作中遇到的一個(gè)需求,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
vue+vuex+axios從后臺(tái)獲取數(shù)據(jù)存入vuex,組件之間共享數(shù)據(jù)操作
這篇文章主要介紹了vue+vuex+axios從后臺(tái)獲取數(shù)據(jù)存入vuex,組件之間共享數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
詳解如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vuex
本篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vuex,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
Vue 組件(component)教程之實(shí)現(xiàn)精美的日歷方法示例
組件是我們學(xué)習(xí)vue必須會(huì)的一部分,下面這篇文章主要給大家介紹了關(guān)于Vue 組件(component)教程之實(shí)現(xiàn)精美的日歷的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01

