6

通过实例了解vue3.3更新的特征 - 南风晚来晚相识

 1 year ago
source link: https://www.cnblogs.com/IwishIcould/p/17450015.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

通过实例了解vue3.3更新的特征 - 南风晚来晚相识 - 博客园

5月份,vue团队发布了 vue3.3.
这次小版本的发布主要解决了--
Vue 与 TypeScript 一起使用时的许多长期存在的痛点.
下面我们一起来学习一下vue3.3新特征

准备新新特征的环境

根据官方团队的描述,我们需要准备一下工作。
vue升级到 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)

使用vite来学习vue3.3的新特征

1.yarn create vite      创建vite项目
2.输出项目名
3.选择包名
4.选择vue
5.选择ts
1425695-20230601192416226-45411168.png
Vue Language Features (Volar) 需要版本 v1.7.2以上
你可以点击设置小图标 然后选择切换版本
也可安装一下 TypeScript Vue Plugin (Volar) 插件

script setup + TypeScript 开发体验改善

在3.3以前,defineProps 和 defineEmits 的使用类型仅限于本地类型,并且仅支持类型文本和接口。
这是因为 Vue 需要能够分析 props 接口上的属性,以便生成相应的运行时选项。
现已在 3.3 中解决。编译器现在可以解析导入的类型,并支持一组有限的复杂类型:

解析导入的类型,并支持有限的复杂类型

//hello.ts文件
// 给HelloWord组件定义类型
export interface HelloPerson {
  name: string;
  age: number;
  likeArr: string[]
}
//HelloWorld.vue文件
<template>
  <div class="card">
    <p>姓名 {{ name }}</p>
    <p>年龄 {{ age }}</p>
    <p>爱好 {{ likeArr }}</p>
  </div>
</template>

<script setup lang="ts">
//导入我们定义的类型
import { HelloPerson } from './hello'
// 使用定义的类型
defineProps<HelloPerson>()
</script>
//在页面中使用
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
  <div>
    <HelloWorld name="张三" :age="19" :likeArr="['打豆豆','挖呀挖']" />
  </div>
</template>
1425695-20230601192955498-1319533583.jpg
1425695-20230601192959732-2068074354.png
1425695-20230601193002763-1957074346.png

需要注意的点

1.组件中 defineProps我使用的是接口 interface 定义。
所以使用组件的时候接口中的参数必须要有,否者会有红色波浪线。
但在实际的场景中,我们有可能不需每一个参数。
为了解决这个上述问题。
我们需要将 interface 中的字段改为可选。使用 ? 还处理。
变为下面的样子就可以了。


// 给HelloWord组件定义类型
//  ? 表示该字段可以有也可以没有
export interface HelloPerson {
  name?: string;
  age?: number;
  likeArr?: string[]
}
1425695-20230601193013353-429287742.png
1425695-20230601193016360-1636439332.png

类型的扩展

有些时候我们还需要进行类型的扩展。
HelloPerson接口中没有我们需要的类型。
我们可以自己进行扩展,现在我们扩展一个其他类型
otherProp 为字符串,同样的这个类型是可有可无的
<script setup lang="ts">
//导入我们定义的类型
import { HelloPerson } from './hello'
// 使用定义的类型 同时还扩展了otherProp类型为字符串。
// 同样的这个类型是可有可无的
defineProps<HelloPerson & { otherProp?: string }>()
</script>
1425695-20230601193207768-1018904326.png

需要注意的点

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

通用组件-组件可以接收泛型参数

有些时候我们不知道,传递过来的是什么类型。
这个时候我们就可以使用泛型了。
// Hi组件
<template>
  <div class="card">
    <p>爱好 {{ likeArr }}</p>
    <p>性别 {{ sex }}</p>
  </div>
</template>

<script setup lang="ts" generic="T">
defineProps<{
  likeArr: T[]
  sex: T
}>()
</script>
<script setup lang="ts">
import Hi from './components/Hi.vue'
let likeArr = ['摸鱼','睡觉']
</script>
<template>
  <div>
    // 在使用的时候会自动推导类型的
    <Hi :likeArr="likeArr" sex="男"/>
  </div>
</template>
1425695-20230601193027687-1952040008.png
多个泛型使用逗号隔开,于此同时,也是可以继承的
<template>
  <div class="card">
    <p>爱好 {{ likeArr }}</p>
    <p>性别 {{ sex }}</p>
    <p>年龄 {{ age }}</p>
  </div>
</template>

<script setup lang="ts" generic="T,U extends number">
// 让U这个泛型继承数字
defineProps<{
  likeArr: T[]
  sex: T,
  age: U
}>()
</script>
<script setup lang="ts">
import Hi from './components/Hi.vue'
let likeArr = ['摸鱼','睡觉']
</script>
<template>
  <div>
    <Hi :likeArr="likeArr" sex="男" :age="10" />
  </div>
</template>
<style scoped>
1425695-20230601193035544-364863387.png

defineEmits的优化--现在

<template>
  <div class="card">
   <button @click="handlerSay">说</button>
   <button @click="handlerWrite">写</button>
  </div>
</template>

<script setup lang="ts" generic="T,U extends number">
const emit = defineEmits<{
  //这里的id是自定义的,你也可以叫其他
  foo: [id: number];  
  //这里的name, age是自定义的,你也可以叫其他
  bar:[name:string, age:number]
}>()
function handlerSay() {
  emit('foo',1)
}
function handlerWrite() {
  emit('bar',  '张三', 19)
}
</script>
<script setup lang="ts">
import Say from './components/Say.vue'
function bar(a,b) {
  console.log(a,b)
}
</script>
<template>
  <div>
    <Say @bar="bar" />
  </div>
</template>

defineEmits以前的写法

<template>
  <div class="card">
   <button @click="handlerSay">说</button>
   <button @click="handlerWrite">写</button>
  </div>
</template>


const emit = defineEmits<{
  (e: 'foo', id: number): void
  (e: 'bar', name: string,  age: number): void
}>()

function handlerSay() {
  emit('foo',1)
}
function handlerWrite() {
  emit('bar',  '张三', 19)
}
如果你觉得我写的不错的话,请给在下方给我点一下推荐。谢谢啦。
如果这篇文章帮助你了,请给打赏。谢谢。
我敢保证,打赏点赞的今年都可以找到女朋友

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK