首页
Preview

Vue 3.3 发布前瞻

今天我们很高兴地宣布Vue 3.3 “Rurouni Kenshin”版本的发布!这个版本着重于开发者体验的提升,特别是在TypeScript中使用SFC <script setup>的使用。与Vue Language Tools(以前称为Volar)的1.6版本一起,我们解决了使用Vue和TypeScript时的许多长期存在的问题。本文提供了3.3版本中的重点功能概述。有关完整的更改列表,请参阅GitHub上的完整更改日志


依赖项更新 升级到3.3时,建议同时更新以下依赖项:

  • volar / vue-tsc@^1.6.4
  • vite@^4.3.5
  • @vitejs/plugin-vue@^4.2.0
  • vue-loader@^17.1.0 (if using webpack or vue-cli)

<script setup> + TypeScript DX 改进

宏中的导入和复杂类型支持

先前,在definePropsdefineEmits的类型参数位置中使用的类型仅限于本地类型,并且仅支持类型文字和接口。这是因为Vue需要能够分析道具接口上的属性,以生成相应的运行时选项。在3.3中,这个限制得到了解决。编译器现在可以解析导入的类型,并支持有限的一组复杂类型:

<script setup lang="ts">
import type { Props } from './foo'

// imported + intersection type
defineProps<Props & { extraProp?: string }>()
</script>

请注意,复杂类型支持是基于AST的,因此不是100%全面的。一些需要实际类型分析的复杂类型,例如条件类型,不受支持。你可以使用条件类型作为单个道具的类型,但不能用于整个道具对象。

泛型组件

使用<script setup>的组件现在可以通过generic属性接受泛型类型参数:

<script setup lang="ts" generic="T">
defineProps<{
  items: T[]
  selected: T
}>()
</script>

generic的值与TypeScript中<...>之间的参数列表完全相同。例如,你可以使用多个参数,extends限制,默认类型和引用导入的类型:

<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中默认启用。

更符合人体工学的defineEmits

以前,defineEmits的类型参数仅支持调用签名语法:

// 以前
const emit = defineEmits<{
  (e: 'foo', id: number): void
  (e: 'bar', name: string, ...rest: any[]): void
}>()

类型与 emit 的返回类型匹配,但写起来有些冗长和笨拙。3.3 引入了一种更符合人体工学的声明类型的方法:

// 现在
const emit = defineEmits<{
  foo: [id: number]
  bar: [name: string, ...rest: any[]]
}>()

在类型字面量中,键是事件名称,值是指定其他参数的数组类型。虽然不是必需的,但你可以使用labeled tuple elements以明确性,就像上面的例子一样。 调用签名语法仍然受支持。

带类型的插槽与defineSlots

新的 defineSlots 宏可用于声明期望的插槽及其各自的期望插槽属性:

<script setup lang="ts">
defineSlots<{
  default?: (props: { msg: string }) => any
  item?: (props: { id: number }) => any
}>()
</script>

defineSlots() 只接受类型参数而不接受运行时参数。类型参数应该是一个类型字面量,其中属性键是插槽名称,值是插槽函数。函数的第一个参数是插槽期望接收的 props,其类型将用于模板中的插槽 props。defineSlots 的返回值与 useSlots 返回的相同的插槽对象。 目前存在一些限制:

  • 必需插槽检查尚未在 volar / vue-tsc 中实现。
  • 插槽函数的返回类型当前被忽略,可以是 any,但是我们可能会在将来利用它进行插槽内容检查。

还有一个相应的 slots 选项可用于 defineComponent 使用。这两个 API 没有运行时影响,仅作为 IDE 和 vue-tsc 的类型提示。

实验性功能

反应式 Props 解构

此前属于现在已删除的 Reactivity Transform 的一部分,反应式 Props 解构已拆分为单独的功能。 该功能允许解构的 Props 保持反应性,并提供了一种更符合人体工学的方式来声明 Props 默认值:

<script setup>
import { watchEffect } from 'vue'

const { msg = 'hello' } = defineProps(['msg'])

watchEffect(() => {
  // 在 watcher 和 computed getter 中访问 `msg`
  // 作为依赖项跟踪,就像访问 `props.msg` 一样
  console.log(`msg is: ${msg}`)
})
</script>

<template>{{ msg }}</template>

此功能是实验性的,需要明确选择。

defineModel

此前,为了使组件支持双向绑定 v-model,它需要 (1) 声明一个 prop,(2) 在意图更新 prop 时发出相应的 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 宏简化了使用。该宏自动注册一个 prop,并返回一个可直接修改的 ref:

<!-- 现在 -->
<script setup>
const modelValue = defineModel()
console.log(modelValue.value)
</script>

<template>
  <input v-model="modelValue" />
</template>

此功能是实验性的,需要明确选择。

其他值得注意的功能

defineOptions

新的 defineOptions 宏允许在 <script setup> 中直接声明组件选项,而不需要单独的 <script> 块:

<script setup>
defineOptions({ inheritAttrs: false })
</script>

更好的 Getter 支持:toReftoValue

toRef 已经被增强,支持将值/Getter/现有的 refs 规范化为 refs:

// 等价于 ref(1)
toRef(1)
// 创建一个只读的 ref,在 .value 访问时调用 getter
toRef(() => props.foo)
// 直接返回现有的 refs
toRef(existingRef)

使用 getter 调用 toRef 类似于 computed,但在 getter 只执行属性访问而没有昂贵计算时,可以更有效率。新的 toValue 实用方法提供了相反的功能,将值/Getter/refs 规范化为值:

toValue(1) //       --> 1
toValue(ref(1)) //  --> 1
toValue(() => 1) // --> 1

在可组合中,可以使用 toValue 代替 unref,以便你的可组合可以接受 getter 作为响应式数据源:

// 之前:分配不必要的中间 refs
useFeature(computed(() => props.foo))
useFeature(toRef(props, 'foo'))

// 之后:更有效率和简洁
useFeature(() => props.foo)

toReftoValue 之间的关系类似于 refunref 之间的关系,主要的区别在于 getter 函数的特殊处理。

JSX 导入源支持

目前,Vue 的类型自动注册全局 JSX 类型。这可能会与需要 JSX 类型推断的其他库一起使用时发生冲突,特别是 React。 从 3.3 开始,Vue 支持通过 TypeScript 的 jsxImportSource 选项指定 JSX 命名空间。这允许用户根据其用例选择全局或每个文件的选择加入。 为了向后兼容,3.3 仍会全局注册 JSX 命名空间。**我们计划在 3.4 中删除默认的全局注册。**如果你正在使用 Vue 的 TSX,请在升级到 3.3 后向你的 tsconfig.json 添加显式的 jsxImportSource,以避免在 3.4 中出现破坏。

维护基础设施改进

此版本建立在许多维护基础设施改进之上,这些改进使我们能够更快地、更有信心地前进:

  • 将类型检查与 rollup 构建分离,并从 rollup-plugin-typescript2 移动到 rollup-plugin-esbuild,使构建速度提高了 10 倍。
  • 通过从 Jest 到 Vitest,测试速度更快。
  • 通过从 @microsoft/api-extractor 移动到 rollup-plugin-dts,类型生成速度更快。
  • 通过 ecosystem-ci 进行全面的回归测试,捕获重大生态系统依赖项在发布之前的回归。

正如计划的那样,我们计划从 2023 年开始进行更小、更频繁的功能发布。敬请期待!

译自:https://blog.vuejs.org/posts/vue-3-3#experimental-features

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
siddhan
软件开发、运动、娱乐

评论(0)

添加评论