体验一下vue3.3发布的船新版本

最近 vue 发布了 3.3 版本,新增了不少宏和语法糖以及改进了一些过往的写法以提高开发者的体验,下面带领大家体验一下 Vue3.3 版本。本篇文章将使用 vite 进行演示。

注意,当我们使用npm create vite的时候 vue 默认的版本还是 3.2 版本,所以我们需要手动将 vue 以及其它改成如下版本在进行 install

安装完毕我们便可以体验最新 3.3.4 版本了

宏函数 defineOptions

或许有的同学在做需要为组件命名的时候见过这个函数,但是是通过unplugin-vue-define-options插件实现的,而在 3.3 版本中它已经被纳入了 Vue 中

现在开发 vue3 项目基本都是用的 setup 语法的形式,这种形式在以前如果想要给组件命名则还需要写一个 script 标签或者使用插件,譬如

  • 额外的 script 标签
js 复制代码
<script>
export default {
  name: 'MyComponent',
}
</script>

<script setup>
...
</script>

这种显然不是很美观

  • 使用插件unplugin-vue-define-options
js 复制代码
//vite.config.ts
import DefineOptions from 'unplugin-vue-define-options/vite'

export default defineConfig({
  plugins: [
    DefineOptions(),
  ]
})

//setup 中
<script setup>
defineOptions({
  name: 'mycomponent'
})
</script>

而在 3.2 中则可以直接使用,当然传入的属性也不止 name 一种,比如有在 setup 中不能使用的beforeCreate生命周期等

js 复制代码
defineOptions({
  name: "mycomponent",
  beforeCreate() {
    console.log(123);
  },
});

便捷的 defineEmits

在 3.3 之前使用 defineEmits 向父组件发送一个 sendMsg 事件的时候写法如下

js 复制代码
defineEmits<{
  (e: 'sendMsg', value: string): void
}>()

第一个参数代表事件名,后面的参数表示传递的事件传递的参数,看起来不是很直观,所有 vue3.3 增加了语法糖

js 复制代码
defineEmits<{
  'sendMsg': [value:string]
}>()

提高类型导入体验

在 3.3 之前组件类型的引入只能引入本地的类型,不同从其它文件中导入,比如如下写法在 3.3 之前是不支持的,而在 vue3.3 版本得到了支持

js 复制代码
import type { Props } from './types'
defineProps<Props>()

并且还支持了一些复杂的类型,比如你想让组件接收一个额外的类型 name 你可以这样写

js 复制代码
defineProps<Props & { name?: string }>()

泛型组件 Generic

vue3.3 中泛型组件主要是用来约束组件接收的参数,比如想接收一个 name 为 string 类型的对象,它的写法如下

js 复制代码
<script lang='ts' setup generic="T extends { name:string }">
defineProps<T>()
</script>

reactive 解构

这个功能可以让我们结构 props 并且不会失去响应式,比如

js 复制代码
<script lang='ts' setup generic="T extends { name:string }">
const { name } = defineProps<T>()
</script>

其中的 name 变量依然是响应式的。 这个功能是实验性 的,如果要使用需要在vite.config.ts中配置

js 复制代码
export default {
  plugins: [
    vue({
      propsDestructure: true,
    }),
  ],
};

defineModel

在以前如果想要组件支持 v-model,我们需要这样写

  • 子组件

先声明 props,当想要更新 props 的时候,emit 一个update:modelValue事件

js 复制代码
<template>
    <div @click="sendMsg">按钮</div>
</template>

<script lang='ts' setup>
const props = defineProps<{ modelValue: string }>()
const emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()
const sendMsg = () => emit('update:modelValue', '222')
</script>
  • 父组件

v-model='msg'其实是:modelValue='msg' @update:modelValue='msg=$event'的语法糖,此时我们点击按钮 msg 就会更新为 222

js 复制代码
<template>
  <div>
    <Comp v-model="msg" />
  </div>
  <div>{{ msg }}</div>
</template>

<script lang='ts' setup>
import Comp from './App2.vue'
import { ref } from 'vue';
const msg = ref('')
</script>

这种写法是不是很麻烦,而使用了 defineModel 宏就会变得很简单,只需要定义一个 modelValue 即可

  • 子组件
js 复制代码
<template>
    <div @click="sendMsg">点击</div>
</template>

<script lang='ts' setup>
const modelValue = defineModel()
const sendMsg = () => {
    modelValue.value = '222'
}
</script>

这样就能实现同样的功能,同样的 defineModel 也是一个实验性的功能,如果想用它则需要在vite.config.ts中进行定义

js 复制代码
export default defineConfig({
  plugins: [
    vue({
      script: {
        defineModel: true,
      },
    }),
  ],
});

defineSlots

defineSlots 可以定义一个插槽的类型,比如子组件

js 复制代码
<template>
    <div>
        <div>
            <slot name="a" foo="yueyue" :bar="1" />
        </div>
        <div>
            <slot name="b" :option="{ name: '小月', age: 18 }" />
        </div>
    </div>
</template>

<script lang='ts' setup>
defineSlots<{
    a(props: { foo: string; bar: number }): any,
    b(props: { option: { name: string, age: number, sex?: string } }): any
}>()
</script>

它包含了两个插槽分别为 a 和 b,同时我们用defineSlots给他们定义了类型,然后我们可以在父组件中使用

js 复制代码
<template>
  <div>
    <Comp>
      <template #a="{ foo, bar }">
        {{ foo }} is string,{{ bar }} is number
      </template>
      <template #b="{ option }">
        {{ option.name }}
      </template>
    </Comp>
  </div>
</template>

<script lang='ts' setup>
import Comp from './App2.vue'
</script>

有了 defineSlots 用户就能更好地确定自己该怎么用某个 scopeSlot 了。

除了这些 Vue3.3 还做了性能的优化和一些小的改动这里就不再列举,更多细节大家可以点击这里查看

相关推荐
泯泷13 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
野槐16 小时前
前端项目优化(有了我,会发生...)
前端
aa小小17 小时前
【无标题】
前端
计算机魔术师18 小时前
还在单线程跟 AI 聊天?Claude Code 并行多会话让你一个人干三个人的活
前端
志尊宝18 小时前
Vue3 零基础每日笔记(038):亲手封装 useDebounceFn 与 useThrottleFn——高频事件的流量阀
前端·javascript·vue·html·vue3
JavaGuide18 小时前
对标 MinIO!全新一代分布式文件系统正式发布
前端·后端
风骏时光牛马18 小时前
AI驱动自动化业务工作流搭建实践
前端
码云之上18 小时前
Skill 里的脚本终于能跑了,星悟接 CubeSandbox 的纪实
前端·人工智能·前端框架
IT_陈寒18 小时前
Vue computed属性这个坑,我居然踩了三次才爬出来
前端·人工智能·后端
烈风逍遥19 小时前
第三篇:组件化实践,SpTable 通用表格组件设计
前端·架构