likes
comments
collection
share

【Vue3.3新特性介绍】与时俱进,一天进步一点点

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

前情提要

最近加入 varlet 后才发现原来ui库需要紧跟vue的更新迭代,也就是说每次 vue / vite 每次更新后,varlet 也需要同步更新, 只有这样才能保证大家使用时不会出现问题,同时可以兼容新特性。

作为一个多年的 vue 开发者,学学学早已是我们的日常习惯了,各种小玩意大玩意早学早香香~

最近关注了几个vue、vite的核心开发人员,他们普遍年龄很小,不少都是大学生或者刚毕业的。江山代有才人出,默默羡慕钦佩的同时,忍不住有了危机感。后浪这么强势,同时伴随着AI的加入,作为“大龄”开发的我们该何去何从呢?人人都会焦虑,但并非人人都会冷静理性的去继续做好手里的事。

  • 每次大浪淘沙后留下的才是“胜利者”
  • 人与人的差别往往不是一次拉开的,而是日积月累的“每次多前进一小步”
  • 有输入就得有输出,这才是一个学习的完整闭环。学习新知识,需要及时运用才能掌握的更好。

这次为varlet更新做准备的同时,为做笔记也为分享(爱因斯坦和查理芒格说过:复利是世界的第八大奇迹),于是有了此文。这里需要引用一段成甲在《好好学习》里的经典语句:

复利效应:做事情A,会导致结果B ,而结果B又会导致事情A,不断循环,直到触发临界点。 生活中如何应用复利思维,成为少数20%呢?首先,要找到A导致B,B加强A的事。其次要尽可能提高这件事的利率,也就是强化作用(利率)。最后,要加强这件事重复发生的可能性(执行次数)。

新特性一览

  • 泛型组件

  • 在 SFC(单文件组件)中导入外部 TS 类型

  • defineSlots 来定义插槽的类型

  • defineEmits 更便捷的语法

  • defineOptions 定义组件选项

  • (试验性) 响应式的 props 解构(实验性本文不做介绍)

  • (试验性) defineModel 语法糖(实验性本文不做介绍)

  • 废弃 Reactivity Transform

泛型组件

泛型是一种在编程语言中广泛使用的概念,它可以在编译时对代码进行类型检查,从而提高代码的可靠性和可维护性。在 Vue3 中,我们可以使用泛型来创建更加灵活和可复用的组件。

什么是泛型组件?

泛型组件(Generic component)是一种可以根据传入的参数类型自动生成组件的机制。在 Vue3 中,我们可以使用 <script setup> 语法来定义泛型组件。

如何定义泛型组件?

在 Vue3 中,我们可以使用通用类型参数generic来定义组件的 props 和返回值类型。

此功能以前需要明确选择加入,但在最新版本的 volar / vue-tsc 中默认启用。

<template>
  <div>
    <slot v-for="(item, index) in list" :name="`item-${index}`" :item="item" />
  </div>
</template>

<script setup lang="ts" generic="T extends string | number, U extends Item">

type Item {
  name: string
  id: number
}
    
const list = defineProps<{ title: T, user: U[] }>()
</script>

在 setup 函数中,我们将 props 参数解构出来,并返回一个包含 list 属性的对象。

泛型组件的优势

泛型组件有以下优势:

  1. 灵活性:泛型组件可以根据不同的参数类型生成不同的组件,从而提高了组件的灵活性和可复用性。
  2. 类型安全:泛型组件可以在编译时对参数类型进行检查,从而提高了代码的可靠性和可维护性。
  3. 简洁性:泛型组件可以使用 <script setup generic="T"> 语法来定义,从而使得代码更加简洁和易于使用。

在 SFC(单文件组件)中导入外部 TS 类型

defineSlots 来定义插槽的类型

在Vue3.3中,我们可以使用defineSlots函数来自定义插槽的类型,它会自动推导类型。以便帮助我们更好地管理插槽,并提供更好的类型安全性。

实现

defineSlots函数是在Vue组件实例对象中被调用的,它接受一个参数,该参数是一个对象,用于定义插槽。这个对象的属性名代表插槽的名称,属性值则代表插槽的类型。只接受类型参数,不接受运行时参数。

注意:对运行时没有影响,纯粹用作 IDE 和vue-tsc

下面是一个示例:

type Slots = {
  default?: (props: { data: string }) => any;
  item?: (props: { id: number }) => any;
};
const slots = defineSlots<Slots>();

defineOptions 宏

<script setup>提供了2个宏,用以定义 Options API 的选项: propsemitsname和其他自定义属性。否则我们就得使用2个<script>标签,而使用2个<script>标签会带来各种麻烦。

  • 两个 script 标签可能会对 ESLint 插件或 Volar 有非预期的问题;
  • 如果两个 script 标签都存在 import 语句,Vue 会做一些奇怪的特殊处理;
  • 对于 DX (开发者体验)来说,不仅麻烦,还难以理解。

使用案例

<script setup>
defineOptions({
  name: 'Foo',
  inheritAttrs: false,
  // ... 更多自定义属性
})
</script>

defineEmits 更便捷的语法

纯粹的语法糖。

vue 为了让开发者少写几个字符也是拼尽全力了。忍不住夸一句:干得漂亮!

<script setup lang="ts">
const emits = defineEmits<{
  (evt: 'update:modelValue', value: string): void
  (evt: 'change'): void
}>()

// ⬇️ Vue 3.3 之后
const emits = defineEmits<{
  'update:modelValue': [value: string],
  'change': []
}>()
</script>

废弃 Reactivity Transform 语法糖

后记

人生如戏,多多尝试