Vue 3.3 發(fā)布了,來(lái)看看有哪些更新~
來(lái)源:
奇酷教育 發(fā)表于:
2023-05-12 17:06:30
Vue 3 3 發(fā)布了,來(lái)看看有哪些更新~
Vue 3.3 發(fā)布了,來(lái)看看有哪些更新~
此版本專注于開發(fā)人員體驗(yàn)改進(jìn)-特別是SFC<script setup>與TypeScript的使用。與Vue語(yǔ)言工具[1](以前稱為Volar)的1.6版本一起,我們?cè)趯ue與TypeScript一起使用時(shí)解決了許多長(zhǎng)期存在的痛點(diǎn)。這篇文章概述了3.3中突出顯示的功能。有關(guān)更改的完整列表,請(qǐng)參閱GitHub上的完整更改日志[2]。
依賴性更新升級(jí)到3.3時(shí),建議也更新以下依賴項(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)
\<腳本設(shè)置> + TypeScript DX改進(jìn)[3]
宏中的導(dǎo)入和復(fù)雜類型支持[4]
通用組件[5]
更符合人體工程學(xué)的定義Emits[6]
帶有定義插槽的類型插槽[7]
實(shí)驗(yàn)特征[8]
響應(yīng)式 props 解構(gòu)[9]
定義模型[10]
其他值得注意的功能[11]
定義選項(xiàng)[12]
使用toRef和toValue提供更好的Getter支持[13]
JSX導(dǎo)入源支持[14]
維護(hù)基礎(chǔ)設(shè)施改進(jìn)[15]
1<script setup>+ TypeScript DX改進(jìn)
宏中的導(dǎo)入和復(fù)雜類型支持
以前,defineProps和defineEmits的類型參數(shù)位置中使用的類型僅限于本地類型,并且僅支持類型文字和接口。這是因?yàn)閂ue需要能夠分析 props 接口上的屬性,以便生成相應(yīng)的運(yùn)行時(shí)選項(xiàng)。這個(gè)限制現(xiàn)在在3.3中得到了解決。編譯器現(xiàn)在可以解析導(dǎo)入的類型,并支持一組有限的復(fù)雜類型:
vue
<script setup lang="ts">
import type { Props } from './foo'
// imported + intersection type
defineProps<Props & { extraProp?: string }>()
</script>
請(qǐng)注意,復(fù)雜類型的支持是基于AST的,因此不是100%全面的。一些需要實(shí)際類型分析的復(fù)雜類型,例如條件類型,不受支持。您可以為單個(gè) prop 的類型使用條件類型,但不能使用整個(gè) prop 對(duì)象。
詳情:PR#8083[16]
通用組件
使用<script setup>的組件現(xiàn)在可以通過(guò)generic屬性接受通用類型參數(shù):
vue
<script setup lang="ts" generic="T">
defineProps<{
items: T[]
selected: T
}>()
</script>
generic的值與TypeScript中<...>之間的參數(shù)列表完全相同。例如,您可以使用多個(gè)參數(shù)、extends約束、默認(rèn)類型和引用導(dǎo)入的類型:
vue
<script setup lang="ts" generic="T extends string | number, U extends Item">
import type { Item } from './types'
defineProps<{
id: T
list: U[]
}>()
</script>
此功能以前需要顯式選擇加入,但現(xiàn)在在最新版本的volar / vue-tsc中默認(rèn)啟用。
討論:RFC#436[17]
相關(guān):通用`defineComponent()`\-PR#7963[18]
更符合人體工程學(xué)defineEmits
以前,defineEmits的類型參數(shù)僅支持調(diào)用簽名語(yǔ)法:
ts
// BEFORE
const emit = defineEmits<{
(e: 'foo', id: number): void
(e: 'bar', name: string, ...rest: any[]): void
}>()
The type matches the return type foremit, but is a bit verbose and awkward to write. 3.3 introduces a more ergonomic way of declaring emits with types:
ts
// AFTER
const emit = defineEmits<{
foo: [id: number]
bar: [name: string, ...rest: any[]]
}>()
在類型字面值中,鍵是事件名稱,值是指定附加參數(shù)的數(shù)組類型。雖然不是必需的,但您可以使用標(biāo)記的元組元素[19]來(lái)顯式,如上例所示。仍然支持調(diào)用簽名語(yǔ)法。
鍵入的插槽defineSlots
新的defineSlots宏可用于聲明預(yù)期插槽及其各自的預(yù)期插槽prop:
vue
<script setup lang="ts">
defineSlots<{
default?: (props: { msg: string }) => any
item?: (props: { id: number }) => any
}>()
</script>
defineSlots()只接受類型參數(shù),不接受運(yùn)行時(shí)參數(shù)。類型參數(shù)應(yīng)該是類型文字,其中屬性鍵是插槽名稱,值是插槽函數(shù)。該函數(shù)的第一個(gè)參數(shù)是插槽期望接收的prop,其類型將用于模板中的插槽 prop。defineSlots的返回值與useSlots返回的插槽對(duì)象相同。目前的一些限制:
所需的插槽檢查尚未在volar / vue-tsc中實(shí)現(xiàn)。
插槽函數(shù)返回類型目前被忽略,可以是any,但我們將來(lái)可能會(huì)利用它進(jìn)行插槽內(nèi)容檢查。
還有一個(gè)相應(yīng)的slots選項(xiàng)用于defineComponent使用。這兩個(gè)API都沒(méi)有運(yùn)行時(shí)影響,純粹作為IDE和vue-tsc的類型提示。
詳情:PR#7982[20]
2實(shí)驗(yàn)特征
響應(yīng)式 prop 解構(gòu)
以前是現(xiàn)已放棄的響應(yīng)性變換的一部分,響應(yīng)式的解構(gòu)已被拆分為一個(gè)單獨(dú)的功能。該功能允許非結(jié)構(gòu)化的prop保留響應(yīng)性,并提供了一種更符合人體工程學(xué)的方式來(lái)聲明 props 默認(rèn)值:
vue
<script setup>
import { watchEffect } from 'vue'
const { msg = 'hello' } = defineProps(['msg'])
watchEffect(() => {
// accessing `msg` in watchers and computed getters
// tracks it as a dependency, just like accessing `props.msg`
console.log(`msg is: ${msg}`)
})
</script>
<template>{{ msg }}</template>
此功能是實(shí)驗(yàn)性的,需要明確選擇加入。
詳情:RFC#502[21]
defineModel
以前,為了使組件支持與v-model雙向綁定,它需要(1)聲明prop,(2)在打算更新prop時(shí)發(fā)出相應(yīng)的update:propName事件:
vue
<!-- BEFORE -->
<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簡(jiǎn)化了使用新的defineModel宏的使用。宏會(huì)自動(dòng)注冊(cè)一個(gè)Props,并返回一個(gè)可以直接突變的引用:
vue
<!-- AFTER -->
<script setup>
const modelValue = defineModel()
console.log(modelValue.value)
</script>
<template>
<input v-model="modelValue" />
</template>
此功能是實(shí)驗(yàn)性的,需要明確選擇加入。
詳細(xì)信息:RFC#503[22]
3其他值得注意的功能
defineOptions
新的defineOptions宏允許直接在<script setup>聲明組件選項(xiàng),而無(wú)需單獨(dú)的<script>塊:
vue
<script setup>
defineOptions({ inheritAttrs: false })
</script>
使用toRef和更好的Getter支持toValue
toRef已增強(qiáng),以支持將值/獲取器/現(xiàn)有引用標(biāo)準(zhǔn)化為引用:
js
// equivalent to ref(1)
toRef(1)
// creates a readonly ref that calls the getter on .value access
toRef(() => props.foo)
// returns existing refs as-is
toRef(existingRef)
使用getter調(diào)用toRef類似于computed,但當(dāng)getter只是在沒(méi)有昂貴計(jì)算的情況下執(zhí)行屬性訪問(wèn)時(shí),效率會(huì)更高。新的toValue實(shí)用程序方法提供了相反的,將值/獲取器/引用標(biāo)準(zhǔn)化為值:
toValue(1) // --> 1
toValue(ref(1)) // --> 1
toValue(() => 1) // --> 1
toValue可以在可組合物中代替unref,以便您的可組合物可以接受獲取者作為響應(yīng)性數(shù)據(jù)源:
// before: allocating unnecessary intermediate refs
useFeature(computed(() => props.foo))
useFeature(toRef(props, 'foo'))
// after: more efficient and succinct
useFeature(() => props.foo)
toRef和toValue之間的關(guān)系與ref和unref之間的關(guān)系相似,主要區(qū)別是getter函數(shù)的特殊處理。
詳情:PR#7997[23]
JSX導(dǎo)入源支持
目前,Vue的類型會(huì)自動(dòng)注冊(cè)全局JSX類型。這可能會(huì)導(dǎo)致與其他需要JSX類型推理的庫(kù)一起使用的沖突,特別是React。從3.3開始,Vue支持通過(guò)TypeScript的jsxImportSource[24]選項(xiàng)指定JSX命名空間。這允許用戶根據(jù)他們的用例選擇全局或每個(gè)文件選擇加入。為了向后兼容,3.3仍然在全球范圍內(nèi)注冊(cè)JSX命名空間。我們計(jì)劃在3.4中刪除默認(rèn)的全局注冊(cè)。如果您將TSX與Vue一起使用,您應(yīng)該在升級(jí)到3.3后將顯式j(luò)sxImportSource添加到tsconfig.json,以避免在3.4中損壞。
4維護(hù)基礎(chǔ)設(shè)施改進(jìn)
此版本基于許多維護(hù)基礎(chǔ)設(shè)施改進(jìn),使我們能夠更自信地更快地移動(dòng):
通過(guò)將類型檢查與 rollup 構(gòu)建分開,并從rollup-plugin-typescript2移動(dòng)到rollup-plugin-esbuild,構(gòu)建速度快10倍。
通過(guò)從Jest 遷移到 Vitest[25] 來(lái)加快測(cè)試速度。
通過(guò)從@microsoft/api-extractor移動(dòng)到rollup-plugin-dts更快地生成類型。
通過(guò)ecosystem-ci [26]進(jìn)行綜合回歸測(cè)試-在發(fā)布前捕獲主要生態(tài)系統(tǒng)依賴項(xiàng)的回歸!