✅创作者:陈书予
🎉个人主页:陈书予的个人主页
🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区
🌟专栏地址: 三十天精通 Vue 3
文章目录
- 特征
- 弃用
- 一、 < s c r i p t s e t u p > <script setup> <scriptsetup> + TypeScript 开发体验改善
- 1. 支持类型导入和复杂类型
- 2. 泛型组件
- 3. defineEmits
- 4. 使用 defineSlots 设置 slots 类型
- 二、实验性功能
- 1. reactive 解构
- 2. defineModel
- 三、其他值得注意的功能
- 1. defineOptions
- 2. toRef、toValue 提供 getter 支持
- 四、JSX 导入源支持
特征
- sfc: 支持在 SFC 宏中导入类型 ( #8083 )
- types/slots:
defineSlots
通过宏和slots
选项支持插槽存在/道具类型检查( #7982 ) ( 5a2f5d5 ) - sfc: 支持更符合人体工程学的 defineEmits 类型语法 ( #7992 ) ( 8876dcc )
- sfc: 引入
defineModel
宏和useModel
帮助器 ( #8018 ) ( 14f3d74 ) - reactivity: 改进对反应性 API 中 getter 使用的支持 ( #7997 ) ( 59e8284 )
- compiler-sfc: 添加 defineOptions 宏 ( #5738 ) ( bcf5841 )
- types/jsx: 支持 jsxImportSource,避免全局 JSX 冲突 ( #7958 ) ( d0b7ef3 )
- **dx:**提高道具显示类型的可读性(4c9bfd2)
- app: app.runWithContext() ( #7451 ) ( 869f3fb )
- hasInjectionContext() for libraries (#8111) (5510ce3)
- 允许在模板中访问控制台 ( #6508 ) ( fe76224 ),关闭#7939
- suspense:
<Suspense>
为( #6736 ) ( cb37d0b )引入悬念选项,关闭#5513 - https://github.com/vuejs/core/issues/5513)
- compiler-dom: 将惰性视为布尔属性 ( #8209 ) ( 918ec8a ),关闭#8208
- https://github.com/vuejs/core/issues/8208)
- types: 提供 ExtractPublicPropTypes 实用程序类型 ( bff63c5 ),关闭#5272 #8168
- compiler-sfc: expose parseCache ( 4576548 ), 关闭#8202https://github.com/vuejs/core/issues/8202)
弃用
- 弃用:**弃用@vnode钩子以支持 vue:前缀 ( 5f0394a )
- 弃用:**弃用 v-is 指令 ( bbd8301 )
- 弃用:**默认情况下在 Options API 中展开注入的引用,弃用 app.config.unwrapInjectedRefs ( 526fa3b )
特征和弃用信息来源地址
今天,我们很高兴地宣布发布 Vue 3.3“浪客剑心”!
此版本专注于改进开发人员体验 - 特别是 SFC<script setup>
与 TypeScript 的使用。与Vue 语言工具(以前称为 Volar)的 1.6 版本一起,我们解决了将 Vue 与 TypeScript 一起使用时许多长期存在的痛点。
依赖更新
升级到 3.3 时,建议同时更新以下依赖项:
- volar / vue-tsc@^1.6.4
- vite@^4.3.5
- @vitejs/plugin-vue@^4.2.0
- vue-loader@^17.1.0(如果使用 webpack 或 vue-cli)
一、 < s c r i p t s e t u p > <script setup> <scriptsetup> + TypeScript 开发体验改善
1. 支持类型导入和复杂类型
以前,在 defineProps
和 defineEmits
的类型仅支持本地类型,不能使用 import,并且仅支持类型字面量和 interface。这是因为 Vue 需要能够分析 props 接口上的属性,以生成相应的运行时选项。
这个限制现在在 3.3 中得到解决。编译器现在可以解析导入的类型,并支持有限的复杂类型:
<script setup lang="ts">
import type { Props } from './foo'
// imported + intersection type
defineProps<Props & { extraProp?: string }>()
</script>
请注意,对复杂类型支持是基于AST
的,因此不是 100% 全面的。一些需要实际类型分析的复杂类型,例如条件类型,不受支持。您可以使用条件类型来定义单个 prop 的类型,但不能用于整个 props 对象。
2. 泛型组件
使用 <script setup>
的组件现在可以通过 generic 属性接受泛型类型参数:
<script setup lang="ts" generic="T">
defineProps<{
items: T[]
selected: T
}>()
</script>
generic
的值与 TypeScript 中 <...> 之间
的参数列表用法完全相同。例如,您可以使用多个参数、extend 约束
、默认类型和引用导入的类型:
<script setup lang="ts" generic="T extends string | number, U extends Item">
import type { Item } from './types'
defineProps<{
id: T
list: U[]
}>()
</script>
此功能在最新版本的 volar / vue-tsc 中默认启用。
3. defineEmits
以前,defineEmits
的类型参数仅支持调用签名语法:
// 以前
const emit = defineEmits<{
(e: 'foo', id: number): void
(e: 'bar', name: string, ...rest: any[]): void
}>()
该类型与 emit 的返回类型匹配,但编写起来有点冗长和笨拙。3.3 引入了一种更符合人体工程学的声明带有类型的 emits 的方式:
// 现在
const emit = defineEmits<{
foo: [id: number]
bar: [name: string, ...rest: any[]]
}>()
在类型字面量中,key 是事件名称,value 是事件参数的数组类型(使用标记元组元素的方式)。
以前的函数调用签名语法仍然受支持。
4. 使用 defineSlots 设置 slots 类型
新的defineSlots 宏
可以声明 slots 及其类型:
<script setup lang="ts">
defineSlots<{
default?: (props: { msg: string }) => any
item?: (props: { id: number }) => any
}>()
</script>
defineSlots()
只接受一个类型参数,没有运行时参数。类型参数应该是一个类型字面量
- key 是 slot 名称
- value 是 slot 函数
defineSlots的返回值
与 useSlots
返回的 slots 对象相同。
目前存在的限制:
- volar / vue-tsc 尚未实现 slots 类型检查。
- slot 函数的返回类型目前是忽略的,是任何类型,但我们可能会在将来利用它进行 slot 内容检查。
除了在<script setup>
中使用 defineSlots 定义 slots 类型,还能在 defineComponent
中的 slots 属性中定义
import { SlotsType } from 'vue'
defineComponent({
slots: Object as SlotsType<{
default: { foo: string; bar: number }
item: { data: number }
}>,
setup(props, { slots }) {
expectType<undefined | ((scope: { foo: string; bar: number }) => any)>(
slots.default
)
expectType<undefined | ((scope: { data: number }) => any)>(slots.item)
}
})
这两个 API 都对运行时没有影响,纯粹作为 IDE 和 vue-tsc 的类型提示。
二、实验性功能
1. reactive 解构
之前是 Reactivity Transform 提案的一部分(已被废弃),现在已被拆分为单独的功能。
该功能可以解构的 props 并保持响应性,并提供了一种更符合人体工程学的方式来声明 props 的默认值:
<script setup>
import { watchEffect } from 'vue'
const { msg = 'hello' } = defineProps(['msg'])
watchEffect(() => {
// 在 watch 和 computed 中使用 msg
// 能够正常收集依赖,就好像使用 props.msg
console.log(`msg is: ${msg}`)
})
</script>
<template>{{ msg }}</template>
此功能是实验性的,需要明确的选择加入。以 Vite 为例:
// vite.config.js
export default {
plugins: [
vue({
propsDestructure: true
})
]
}
2. defineModel
以前组件想要支持 v-model,需要两个步骤:
- 声明 props
- 在打算更新 props 时,
emit update:propName 事件
子组件支持 v-model 的写法:
<!-- 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>
父组件:
<script setup>
import { ref } from 'vue'
import Comp from './Comp.vue'
const msg = ref('')
</script>
<template>
<Comp v-model="msg">
</template>
Vue 3.3 用新的 defineModel
宏简化了用法。宏将自动注册 props 和事件 ,并返回一个 ref:
<!-- AFTER -->
<script setup>
const modelValue = defineModel()
console.log(modelValue.value)
</script>
<template>
<input v-model="modelValue" />
</template>
根据接受 defineModel
返回值的变量名,这里是 modelValue
,会自动定义 props 名为 modelValue,emit 事件为 update:modelValue
也支持显示传入 props 名称
const count = defineModel<number>('count', { default: 0 })
此功能是实验性的,需要明确的选择加入。
三、其他值得注意的功能
1. defineOptions
defineOptions 允许直接在 <script setup>
中声明组件选项,而无需单独的 <script> 块
:
<script setup>
defineOptions({ inheritAttrs: false })
</script>
2. toRef、toValue 提供 getter 支持
增强 toRef,支持将 values/getters/ref
标准化为 ref:
// 相当于 ref(1)
toRef(1)
// 创建只读 ref,使用 .value 时执行 getter
toRef(() => props.foo)
// 返回 ref
toRef(existingRef)
调用 toRef 类似于 computed
,但如果 getter
没有昂贵的计算,toRef 会更高效
toValue 则相反
,将 values/getters/ref 标准化为 value:
toValue(1) // --> 1
toValue(ref(1)) // --> 1
toValue(() => 1) // --> 1
四、JSX 导入源支持
目前,Vue 的类型会自动注册全局 JSX 类型。这可能会导致与需要 JSX 类型推断的其他库一起使用时发生冲突,尤其是 React。
从 3.3 开始,Vue 支持通过 TypeScript 的jsxImportSource
选项指定 JSX 命名空间。这允许用户根据他们的用例选择全局或每个文件选择加入。
为了向后兼容,3.3 仍然全局注册 JSX 命名空间。我们计划在 3.4 中移除默认的全局注册。jsxImportSource
如果您将 TSX 与 Vue 一起使用,则应在升级到 3.3 后向您添加 explicittsconfig.json
以避免在 3.4 中损坏。
原文地址