快速了解vue 3


雖然 vue2 到 vue3 的實現大改,但在用法上變化基本不大,比較明顯的一個變化就是添加了 setup(){} 函數了,

幾乎所有的配置變成了以函數的方式進行定義。

即使是這樣,但小改動還是很多的。

這里默認你已經熟練掌握了 vue 2.x 的使用。

 

一、新增composition-api

1.邏輯復用和代碼組織

這是 vue 3.0 的一個核心變更了。除了改了我們定義狀態的書寫方式外,也為我們提供體驗更棒的邏輯復用和代碼組織,

新的方式可以讓你把同一個業務邏輯的代碼(狀態,計算屬性,方法等)都放到一塊。

這聽起來可能有點不明不白,但如果你寫過比較復雜的組件,你就會發現,這個好。

 

2.更好的類型推斷

更好的支持 TypeScript。

teleport 組件

teleport 組件它只是單純的把定義在其內部的內容轉移到目標元素中,在元素結構上不會產生多余的元素,當然也不會影響到組件樹,它相關於透明的存在。為什么要有這個組件?為了有更好的代碼組織體驗。比如:有時,組件模板的一部分在邏輯上屬於此組件,但從技術角度來看(如:樣式化需求),最好將模板的這一部分移動到 DOM 中的其他位置。

比如:一些 UI 組件庫的 模態窗、對話框、通知,下拉菜單等需要通知 z-index 來控制層級關系,如果都只是在不同的組件或者元素層級中,那么 z-index 的層級順序就難以保證。可能你會說很多 UI 庫不是都已經是這樣的實現了的嗎?至於這個 UI 庫是如何實現的,我猜應該是直接操作 DOM。為什么還要提供這個 teleport 組件呢?可能是因為vue 本身的使命使然:盡量不讓開發者直接操作 DOM,這些事都統一由 VUE 來完成。開發者可以把更多的時間放在業務的開發上。

<teleport to="#modals"> <div>A</div></teleport>
<teleport to="#modals"> <div>B</div></teleport>
<!-- result-->
<div id="modals"> <div>A</div> <div>B</div></div>

 

Suspense

加載異步組件,在異步組件加載完成成並完全渲染之前 suspense 會先顯示 #fallback 插槽的內容 。

<Suspense> 
<template> <Suspended-component /> </template>
<template #fallback> Loading... </template>
</Suspense>

 

#fallback 其實是插件 v-solt 的簡寫,而第一個 template 沒有給,則為默認插槽。

 

變更

插槽 slot 語法

適用版本:Version: 2.x,Version: 3.x

未來版本的 vue 中可以說合二為一了(slot 和 slot-scope)

<!-- vue 2.x -->
<foo> <bar slot="one" slot-scope="one">
<div slot-scope="bar"> {{ one }} {{ bar }} </div> </bar>
<bar slot="two" slot-scope="two">
<div slot-scope="bar"> {{ two }} {{ bar }} </div> </bar></foo>

<!-- vue 3.x --> <foo> <template v-slot:one="one"> <bar v-slot="bar"> <div>{{ one }} {{ bar }}</div> </bar></template> <template v-slot:two="two"> <bar v-slot="bar"> <div>{{ two }} {{ bar }} </div></bar> </template></foo>

 

我覺得這是好事,合二為一,不會讓人有一點點的困惑。

簡寫

<TestComponent>
<template #one="{ name }">Hello {{ name }}</template>
</TestComponent>

 

指令動態參數

適用版本:Version: 2.x,Version: 3.x

<!-- v-bind with dynamic key -->
<div v-bind:[key]="value"></div>
<!-- v-bind shorthand with dynamic key -->
<div :[key]="value"></div>

<!-- v-on with dynamic event --> <div v-on:[event]="handler"></div> <!-- v-on shorthand with dynamic event --> <div @[event]="handler"></div> <!-- v-slot with dynamic name --> <foo> <template v-slot:[name]> Hello </template></foo> <!-- v-slot shorthand with dynamic name --> <!-- pending #3 --> <foo> <template #[name]> Default slot </template></foo>

 

簡單地說就是指令名,事件名,插槽名,都可以使用變量來定義了。

Tree-shaking

適用版本:Version: 3.x

在 vue 3 中不會把所有的 api 都打包進來,只會 打包你用到的 api

<!-- vue 2.x --> import Vue from 'vue'Vue.nextTick(() => {})const obj = Vue.observable({})<
 !-- vue 3.x --> import Vue, { nextTick, observable } from 'vue'Vue.nextTick // undefinednextTick(() => {})const obj = observable({})

 

即我們在項目中用什么什么,就只會打包什么,不會像 vue 2.x 那樣全部 api 都打包。

 

.sync 大變樣

適用版本: vue 3.x

<!-- vue 2.x -->
<MyComponent v-bind:title.sync="title" />

<!-- vue 3.x -->
<MyComponent v-model:title="title" />

 

也就是說,vue 3.0 又去掉了 .sync ,合並到了 v-model 里,而 v-model 的內部實現也有了小調整

元素

<input v-model="xxx">

<!-- would be shorthand for: -->

<input :model-value="xxx" @update:model-value="newValue => { xxx = newValue }">

 

組件

<input v-model="xxx">

<!-- would be shorthand for: -->

<input :model-value="xxx" @update:model-value="newValue => { xxx = newValue }">

 

不過好像組 alpha 版本的還不支持 v-model:aaa="xxx"

 

函數組件

適用版本: vue 3.x

<!-- vue 2.x --> const FunctionalComp = { functional: true, render(h) { return h('div', `Hello! ${props.name}`)   } } <!-- vue 3.x --> import { h } from 'vue'const FunctionalComp = (props, { slots, attrs, emit }) => { return h('div', `Hello! ${props.name}`) }

 

不再需要 functional:true 選項,<template functional> 不再支付

異步組件也必需通過 api 方法創建

import { defineAsyncComponent } from 'vue'const AsyncComp = defineAsyncComponent(() => import('./Foo.vue'))

 

全局 api

適用版本: vue 3.x

在 vue 2.x 中 import Vue from 'vue' import App from './App.vue' Vue.config.ignoredElements = [/^app-/] Vue.use(/* ... */) Vue.mixin(/* ... */) Vue.component(/* ... */) Vue.directive(/* ... */) Vue.prototype.customProperty = () => {} new Vue({ render: h => h(App)}).$mount('#app') 在 vue 3.x 中 import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.config.isCustomElement = tag => tag.startsWith('app-') app.use(/* ... */) app.mixin(/* ... */) app.component(/* ... */) app.directive(/* ... */) app.config.globalProperties.customProperty = () => {} app.mount(App, '#app')

 

可以看到,創建實例的方式也改變了。一些全局的 api 方法也不在全局上了,而是放到了實例上。

 

v-model

適用版本:Version 3.x

1.原來的方式保留

<input v-model="foo">

 

2.可綁定多個 v-model

<InviteeForm v-model:name="inviteeName" v-model:email="inviteeEmail"/>

 

其實上面這種方式就相當於之前的 .sync 。

3.額外處理

<Comp v-model:foo.trim="text" v-model:bar.number="number" />

 

我們可以給這個屬性添加額外的處理

指令的鈎子函數

適用版本:Version 3.x

在 vue 3.x 中 指令的鈎子函數仿照了組件中的鈎子函數命名規則

vue 2.x 時 const MyDirective = { bind(el, binding, vnode, prevVnode) {}, inserted() {}, update() {}, componentUpdated() {}, unbind() {} }  vue 3.0 const MyDirective = { beforeMount(el, binding, vnode, prevVnode) {}, mounted() {}, beforeUpdate() {}, updated() {} beforeUnmount() {}, // new unmounted() {}}

 

transition

適用版本:Version 3.x

當 <transition> 作為組件的根元素時,外部切換不會觸發過渡效果

vue 2.x <!-- modal component -->
<template> <transition> <div class="modal"><slot/></div> </transition></template>
<!-- usage -->
<modal v-if="showModal">hello</modal>
 vue 3.x <!-- modal component -->
<template> <transition> <div v-if="show" class="modal"><slot/></div> </transition></template>
<!-- usage -->< modal :show="showModal">hello</modal>

 

也就是說我們只能在 <sransition> 內使用切換。

 

transition-class

重命名兩個過渡類

v-enter 重命名成.v-enter-from,v-leave重命名成 .v-enter-from。

.v-enter-from, .v-leave-to { opacity: 0;}.v-leave-from, .v-enter-to { opacity: 1}

 

Router

適合版本:Version: Vue (2.x / 3.x) Vue Router (3.x / 4.x)

1.router-link 添加 scoped-slot API 和 custom 屬性,並移除了 tag 屬性和 event 屬性。

添加 scoped-slot 有什么用呢?

以前只能通知 active-class 來改變元素樣式的,現在有了 scoped-slot 之后,我們就更加靈活了,可以根據 scoped-slot 回傳的狀態自定義,不管是樣式還是類。

<router-link to="/" custom v-slot="{ href, navigate, isActive }">
<li :class="{ 'active': isActive }">
<a :href="href" @click="navigate"> <Icon>home</Icon><span class="xs-hidden">Home</span>
</a></li></router-link>

 

也就是說,新版本的 Router 就更加的純粹,只提供給我們一些參數,讓我們自己利用這些參數來實現不同的場景。

 

2.meta 合並

{ path: '/parent', meta: { requiresAuth: true, isChild: false }, children: [ { path: 'child', meta: { isChild: true }} ]}

 

當訪問 /parent/child 時,子路由中的 meta 如下:

{ requiresAuth: true, isChild: true }

合並策略與 Object.assign 類似

樣式 scoped

適用版本:Version: 2.x, 3.x

舊版本寫法

/* 深度選擇器 *//*方式一:*/>>> .foo{ }/*方式二:*//deep/ .foo{ }/*方式三*/::v-deep .foo{ }

新版本寫法

/* 深度選擇器 */::v-deep(.foo) {}

除了上面的深度選擇器外,還有下面的兩個,寫法也差不多

/* slot content 起作用 */::v-slotted(.foo) {}/* 全局 */::v-global(.foo) {}復制代碼

屬性值修正

適用版本:Version: 3.x

vue 本身會對元素的屬性作相應的處理。

 

在舊版本的 vue 中處理如下:

 

 

 

在新版本的 vue 中處理如下:

 

 

 

在新版本中基本保持了原樣,也就是我們給元素添加什么屬性值,最好 vue 處理完后還是什么屬性值。

 

異步組件

import { defineAsyncComponent } from "vue"
// simple usageconst AsyncFoo = defineAsyncComponent(() => import("./Foo.vue"))

 

寫法上與之前有些不一樣。

動態路由

適用版本 Router 4

添加了幾個方法

router.addRoute(route: RouteRecord)動態添加路由 router.removeRoute(name: string | symbol),動態刪除路由 router.hasRoute(name: string | symbol): boolean ,判斷路由是否存在 router.getRoutes(): RouteRecord[]獲取路由列表 router.addRoute({ path: '/new-route', name: 'NewRoute', component: NewRoute}) // add to the children of an existing routerouter.addRoute('ParentRoute', { path: 'new-route', name: 'NewRoute', component: NewRoute}) router.removeRoute('NewRoute') // normalized version of the records addedconst routeRecords = router.getRoutes() emits-option const Foo = defineComponent({ emits: { submit: (payload: { email: string; password: string }) => { // perform runtime validation } }, methods: { onSubmit() { this.$emit('submit', { email: 'foo@bar.com', password: 123
// Type error! })
this.$emit('non-declared-event') // Type error! } } })

 

現在的 $emit() 方法在用法上沒變,但需要額外多定義 emits 對象,但要注意的是現在 alpha 版本還不支持 TypeScript

組件根元素數量

vue 3 后組件不再限制 template 中根元素的個數(舊的版本之前是只能有一個根元素)。

vue 3.x 中費棄

filters

keycode

inline-template

data-object

off 和 $once

相信你大概對 vue 3 有了一個基本的認識。

雖然不讓你瞬間成為 vue 3.x 的駕馭者,

但怎么說也含蓄地體驗了一把 vue 3.x 的新特性。

特別是 composition API 即使本文沒有詳細寫出來,但通知補充的鏈接,你也能閱讀到它的所有。我覺得 composition API 真的很棒。

 

原文來自 : https://baijiahao.baidu.com/s?id=1667290129402508440&wfr=spider&for=pc


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM