Vue 3.3 正式發(fā)布,代號(hào):Rurouni Kenshin

5 月 11 日,Vue 3.3 正式發(fā)布,代號(hào) Rurouni Kenshin。本次更新主要針對(duì)開(kāi)發(fā)者體驗(yàn)進(jìn)行了改進(jìn),特別是在使用 TypeScript 時(shí)的 SFC <script setup>。與 Vue 語(yǔ)言工具(以前稱(chēng)為 Volar)1.6 的發(fā)布相結(jié)合,解決了在使用 TypeScript 時(shí)存在的許多長(zhǎng)期困擾問(wèn)題。下面就來(lái)看看 Vue 3.3 版本中的重點(diǎn)功能!
當(dāng)升級(jí)到 Vue 3.3 時(shí),建議同時(shí)更新以下依賴(lài)項(xiàng):
- volar / vue-tsc @ ^1.6.4
- vite @ ^4.3.5
- @vitejs/plugin-vue @ ^4.2.0
- vue-loader @ ^17.1.0(如果使用 webpack 或 vue-cli)
SFC中的 <script setup> 和 TypeScript DX 改進(jìn)
宏中的導(dǎo)入和復(fù)雜類(lèi)型支持
在之前的版本中,用于 defineProps 和 defineEmits 的類(lèi)型參數(shù)位置使用的類(lèi)型被限制為本地類(lèi)型,并且僅支持類(lèi)型字面量和接口。這是因?yàn)?Vue 需要能夠分析 props 接口上的屬性以生成相應(yīng)的運(yùn)行時(shí)選項(xiàng)。
此限制現(xiàn)已在 3.3 中解決。編譯器現(xiàn)在可以解析導(dǎo)入的類(lèi)型,并支持一組有限的復(fù)雜類(lèi)型:
<script setup lang="ts">
import type { Props } from './foo'
// imported + intersection type
defineProps<Props & { extraProp?: string }>()
</script>注意,復(fù)雜類(lèi)型支持是基于AST的,因此不是 100% 全面的。不支持一些需要實(shí)際類(lèi)型分析的復(fù)雜類(lèi)型,例如條件類(lèi)型。可以對(duì)單個(gè) props 的類(lèi)型使用條件類(lèi)型,但不能對(duì)整個(gè) props 對(duì)象使用條件類(lèi)型。
通用組件
使用<script setup>的組件現(xiàn)在可以通過(guò) generic 屬性接受泛型類(lèi)型參數(shù):
<script setup lang="ts" generic="T">
defineProps<{
items: T[]
selected: T
}>()
</script>generic 的值與 TypeScript 中 <...> 之間的參數(shù)列表完全相同。例如,可以使用多個(gè)參數(shù)、extends約束、默認(rèn)類(lèi)型和引用導(dǎo)入類(lèi)型:
<script setup lang="ts" generic="T extends string | number, U extends Item">
import type { Item } from './types'
defineProps<{
id: T
list: U[]
}>()
</script>這個(gè)功能以前需要顯式地選擇,但現(xiàn)在在最新版本的 volar / vue-tsc 中已經(jīng)默認(rèn)啟用了。
更符合人體工程學(xué)的 defineEmits
以前,defineEmits 的類(lèi)型參數(shù)只支持調(diào)用簽名語(yǔ)法:
const emit = defineEmits<{
(e: 'foo', id: number): void
(e: 'bar', name: string, ...rest: any[]): void
}>()該類(lèi)型與 emit 的返回類(lèi)型相匹配,但編寫(xiě)起來(lái)有點(diǎn)冗長(zhǎng)和笨拙。3.3 引入了一種更符合人體工程學(xué)的聲明具有類(lèi)型的 emit 的方法:
const emit = defineEmits<{
foo: [id: number]
bar: [name: string, ...rest: any[]]
}>()在類(lèi)型字面量中,鍵是事件名稱(chēng),值是指定附加參數(shù)的數(shù)組類(lèi)型。雖然不是必需的,但可以使用帶標(biāo)簽的元組元素來(lái)明確表示,就像上面的示例中一樣。
調(diào)用簽名語(yǔ)法仍然受支持。
使用 defineSlots 的類(lèi)型插槽
新的 defineSlots 宏可用于聲明預(yù)期的插槽及其相應(yīng)的預(yù)期插槽 props:
<script setup lang="ts">
defineSlots<{
default?: (props: { msg: string }) => any
item?: (props: { id: number }) => any
}>()
</script>defineSlots() 只接受類(lèi)型參數(shù),不接受運(yùn)行時(shí)參數(shù)。類(lèi)型參數(shù)應(yīng)該是類(lèi)型字面量,其中屬性鍵是插槽名稱(chēng),值是插槽函數(shù)。該函數(shù)的第一個(gè)參數(shù)是插槽期望接收的 props,其類(lèi)型將用于模板中的插槽 props。defineSlots 的返回值與 useSlots 返回的插槽對(duì)象相同。
當(dāng)前的一些限制:
- volar / vue-tsc 中尚未實(shí)現(xiàn)必需的插槽檢查。
- 插槽函數(shù)返回類(lèi)型目前被忽略,可以是 any 類(lèi)型,但將來(lái)可能會(huì)利用它來(lái)檢查插槽內(nèi)容。
defineComponent 用法也有對(duì)應(yīng)的 slots 選項(xiàng)。這兩個(gè) API 都沒(méi)有運(yùn)行時(shí)影響,并且純粹用作 IDE 和 vue-tsc 的類(lèi)型提示。
實(shí)驗(yàn)功能
響應(yīng)式 Props 解構(gòu)
以前是現(xiàn)在已刪除的 Reactivity Transform 的一部分,響應(yīng)式 props 解構(gòu)已拆分為單獨(dú)的功能。
該功能允許解構(gòu)的 props 保持響應(yīng)性,并提供更符合人體工程學(xué)的聲明 props 默認(rèn)值的方式:
<script setup>
import { watchEffect } from 'vue'
const { msg = 'hello' } = defineProps(['msg'])
watchEffect(() => {
// 在 watchers 和 computed getters 中訪(fǎng)問(wèn) `msg`
// 將其作為依賴(lài)項(xiàng)進(jìn)行跟蹤,就像訪(fǎng)問(wèn) `props.msg` 一樣
console.log(`msg is: ${msg}`)
})
</script>
<template>{{ msg }}</template>defineModel
以前,對(duì)于支持與 v-model 雙向綁定的組件,它需要(1)聲明一個(gè) prop 和(2)在打算更新 prop 時(shí)發(fā)出相應(yīng)的 update:propName 事件:
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
console.log(props.modelValue)
function onInput(e) {
emit('update:modelValue', e.target.value)
}
</script>
<template>
<input :value="modelValue" @input="onInput" />
</template>3.3 使用新的 defineModel 宏簡(jiǎn)化了使用。宏會(huì)自動(dòng)注冊(cè)一個(gè) prop,并返回一個(gè)可以直接改變的 ref:
<script setup>
const modelValue = defineModel()
console.log(modelValue.value)
</script>
<template>
<input v-model="modelValue" />
</template>其他特性
defineOptions
新的 defineOptions 宏允許直接在 <script setup> 中聲明組件選項(xiàng),而不需要單獨(dú)的 <script> 塊:
<script setup>
defineOptions({ inheritAttrs: false })
</script>使用 toRef 和 toValue 實(shí)現(xiàn)更好的 getter 支持
toRef 已得到增強(qiáng)以支持將值/getters/現(xiàn)有 refs 規(guī)范化為 refs:
// 相當(dāng)于 ref(1)
toRef(1)
// 創(chuàng)建一個(gè) readonly ref,在 .value 訪(fǎng)問(wèn)時(shí)調(diào)用 getter
toRef(() => props.foo)
// 按原樣返回現(xiàn)有 refs
toRef(existingRef)使用 getter 調(diào)用 toRef 類(lèi)似于 computed,但是當(dāng) getter 只執(zhí)行屬性訪(fǎng)問(wèn)而沒(méi)有昂貴的計(jì)算時(shí),可以更高效。
新的 toValue 工具方法提供相反的功能,即將值/ getter / ref 規(guī)范化為值:
toValue(1) // --> 1
toValue(ref(1)) // --> 1
toValue(() => 1) // --> 1toValue 可以在組合式函數(shù)中代替 unref,以便組合式函數(shù)可以接受 getter 作為響應(yīng)式數(shù)據(jù)源:
// 以前:分配不必要的中間引用
useFeature(computed(() => props.foo))
useFeature(toRef(props, 'foo'))
// 現(xiàn)在:更高效和簡(jiǎn)潔
useFeature(() => props.foo)toRef 和 toValue 之間的關(guān)系類(lèi)似于 ref 和 unref 之間的關(guān)系,主要區(qū)別在于 getter 函數(shù)的特殊處理。
JSX 導(dǎo)入源支持
當(dāng)前,Vue 的類(lèi)型自動(dòng)注冊(cè)全局 JSX 類(lèi)型。這可能會(huì)與需要 JSX 類(lèi)型推斷的其他庫(kù)一起使用時(shí)產(chǎn)生沖突,特別是 React。
從 3.3 開(kāi)始,Vue 支持通過(guò) TypeScript 的 jsxImportSource 選項(xiàng)指定 JSX 命名空間,這允許用戶(hù)基于其用例選擇全局或每個(gè)文件的選擇。
為了向后兼容,3.3 仍然全局注冊(cè) JSX 命名空間。計(jì)劃在 3.4 中刪除默認(rèn)的全局注冊(cè)。如果正在使用 TSX 和 Vue,請(qǐng)?jiān)谏?jí)到 3.3 后在 tsconfig.json 中添加顯式的 jsxImportSource,以避免在 3.4 中出現(xiàn)問(wèn)題。
維護(hù)基礎(chǔ)設(shè)施改進(jìn)
此版本建立在許多維護(hù)基礎(chǔ)設(shè)施改進(jìn)的基礎(chǔ)上,這使得 Vue 團(tuán)隊(duì)能夠更有信心地更快地行動(dòng):
- 通過(guò)將類(lèi)型檢查與匯總構(gòu)建分開(kāi)并從 rollup-plugin-typescript2 移動(dòng)到 rollup-plugin-esbuild,構(gòu)建速度提高 10 倍。
- 通過(guò)從 Jest 轉(zhuǎn)移到 Vitest 來(lái)加快測(cè)試速度。
- 通過(guò)從 @microsoft/api-extractor 轉(zhuǎn)移到 rollup-plugin-dts 來(lái)更快地生成類(lèi)型。
- 通過(guò) ecosystem-ci 進(jìn)行綜合回歸測(cè)試,在發(fā)布前捕獲主要生態(tài)系統(tǒng)依賴(lài)項(xiàng)中的回歸。
按照計(jì)劃,Vue 團(tuán)隊(duì)的目標(biāo)是在 2023 年開(kāi)始發(fā)布更小、更頻繁的功能版本,敬請(qǐng)期待!
參考:https://blog.vuejs.org/posts/vue-3-3。

























