likes
comments
collection
share

Vue 3.3亮点解析:不容错过的新特性及其影响

作者站长头像
站长
· 阅读数 14

这张图看起来不错

概览

Vue 3.3的最新版本主要目标是优化开发者的使用体验,包括引入一些新的简化语法和宏,以及在TypeScript方面的进一步提升。

以下是主要的更新内容:

  1. 为setup语法糖组件引入了泛型功能
  2. 允许在组件文件中导入外部的ts类型
  3. defineEmits语法进行了优化;
  4. 新增-defineSlots定义插槽类型;
  5. 新增-defineModel来简化modelValue的语法;
  6. 新增-defineOptions定义组件名称以及其他一些配置项;
  7. toRef和toValue的功能进行了增强。

接下来对这些改动一一介绍

更新

setup语法糖泛型

使用<script setup>的组件现在可以通过generic属性接受泛型类型参数,一般情况下用不到,但有时候组件笔记复杂时无法推断类型的时候非常有用

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

注意:eslint可能会报错,需要关闭该选项的检查

支持导入外部ts类型

definePropsdefineEmits支持使用import外部导入的类型声明。

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

// 使用导入的类型 + 交集类型(导入类型基础上增加一个字段)
defineProps<Props & { extraProp?: string }>() //在vue3.3之前不支持使用import导入的类型
</script>

defineEmits语法优化

之前defineEmits的类型参数只支持调用签名语法:

const emit = defineEmits<{
  (e: 'foo', id: number): void
  (e: 'bar', name: string, ...rest: any[]): void
}>()
// 或者不定义类型
// const emit = defineEmits(['update:modelValue'])

在vue3.3中可以简化为以下写法,更加简洁(当然原来的写法照样可以继续使用)

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

新增defineSlots

新的defineSlots宏可以用来声明插槽的类型,例如:

子组件Pant

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

父组件

<template>
 <Pant :list="list">
  <template #default="{ msg }">{{ msg }}</template>
 <Pant/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { listType } from '@/types/api'

const list = ref<Array<listType>>([])
</script>

新增defineModel

在vue3.3中此功能是实验性的,需要明确的选择加入

用于简化自定义v-model双向绑定语法,在原来需要声明props,并定义update:propName事件

<template>
  <input :value="modelValue" @input="onInput" />
</template>

<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

function onInput(e) {
  emit('update:modelValue', e.target.value)
}
</script>

简化后的写法

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

<script setup>
const modelValue = defineModel()
// 也可以直接修改,等价于emit('update:modelValue', '新值')
// modelValue.value = '新的值'
</script>

新增 defineOptions

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

可以用 defineOptions 定义任意选项,但 propsemitsexposeslots 除外

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

toRef和toValue增强

toRef已得到增强,以支持将值/getter/现有refs规范化为refs:

js

// 等价于ref(1)
toRef(1)
// 创建一个readonly ref,在.value访问时调用getter
toRef(() => props.foo)
// 按原样返回现有的引用
toRef(existingRef)

使用getter调用toRef类似于computed,但当getter只是执行属性访问而没有昂贵的计算时,效率会更高。

新的toValue实用程序方法提供了相反的功能,将values / getters / refs标准化为值:

js

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

toValue可以在composable中代替unref使用,这样你的composable就可以接受getter作为反应式数据源:

js

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

// 现在:更高效和简洁
useFeature(() => props.foo)

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

关于依赖

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

  • volar / vue-tsc@^1.6.4
  • vite@^4.3.5
  • @vitejs/plugin-vue@^4.2.0
  • vue-loader@^17.1.0(如果使用webpack或vue-cli)

JSX导入源

从3.3版本开始,Vue允许用户通过TypeScript的jsxImportSource选项来指定JSX命名空间,让用户可以根据需要选择全局或按文件进行选择。

尽管如此,为了保持向后兼容性,3.3版本仍然会全局注册JSX命名空间。作者计划在3.4版本中取消默认的全局注册。如果你现在正在使用TSX和Vue,建议升级到3.3版本后,应显式地在tsconfig.json文件中添加jsxImportSource选项,以避免在3.4版本发布时出现问题。

总结

哈哈哈,总结已经在 概览 里面了,本文只记录了一部分比较重点的更新,完整更新日志可以去看vue.js的github日志