Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots - 金色...
source link: https://www.cnblogs.com/jyk/p/17434408.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.
上一篇说了 DefineOptions、defineModel、Props 的响应式解构和从外部导入类型 这几个新功能,但是没有说Generic、defineSlots等,这是因为还没有完全搞清楚可以用在什么地方。折腾了几天终于弄清楚了。
这还要从 TS 的泛型说起。
泛型的目的和意义
泛型仅仅只是表达传啥都行吗?当然不是,因为js原生就支持“泛型”,本来就啥都可以传的。
泛型的目的是——约束!泛型相当于制定了一个白名单,名单里面的类型可以传,不在名单里面的不可以传。
TS 的泛型可以帮助我们更准确的推断类型,从而在编写代码的时候,可以有更准确的提示和提供验证依据。
泛型组件(Generic Component)
组件的props可以设置各种类型,那么如果想用泛型的话,要如何设置呢?这就需要使用 Generic:
<script setup lang="ts" generic="T extends {name: string} ">
const props = defineProps<{
list: T[], // 泛型的方式
list2: number[], // 只能是 number 类型的数组
list3: Array<any>, // 任意类型的数组
name: string,
person: {
name: string
}
}>()
console.log('props-ts:\n', props)
这里定义了几个属性,第一个使用了泛型,第二个是 number[],第三个是任意类型的数组。
我们来看看不同类型的提示信息:
-
Array<any> 提示的时候,无法获知具体的类型。
-
number[] 必须和设置的类型完全一致。
-
T[] 可以根据传入的类型做出对应的提示
-
传入 {name: string}
-
传入 {name: string, age: number}
-
类型不匹配的提示
-
对比一下,我们可以发现,使用泛型可以准确的推断类型,在模板里面可以有更准确的提示,如果类型不合格,可以有提示信息。
这样在编写代码的时候可以避免低级错误。
defineSlots
defineSlots 是做什么的呢,是定义插槽还是获取插槽?准确的说,是定义作用域插槽的props的类型(支持泛型),然后返回父组件传入的插槽。
在 setup 里面定义插槽的类型
在组件里面定义两个插槽,一个是匿名插槽,一个是作用域插槽(col),
定义一个 list 的属性,传入一个数组,然后遍历这个数组,创建一组列表,列表内使用作用域插槽。
通过作用域插槽的props把数组元素传递给父组件:(好像有点绕)
<script setup lang="ts" generic="T extends Object ">
const props = defineProps<{
list: T[], // 泛型的方式
}>()
const slot = defineSlots<{
default(props: any): any,
col(props:
{
row: T,
index: number
}): any
}>()
console.log('slot:\n', slot)
<template>
<!--匿名插槽-->
<slot></slot>
<div v-for="(item, index) in list" :key="index">
<!--作用域插槽-->
<slot name="col" :row="item" :index="index" ></slot>
</div>
</template>
父组件里使用的方法
<script setup lang="ts">
import { reactive } from 'vue'
// 加载子组件
import ts from './20-ts.vue'
// 定义数组
const list2 = reactive([
{
name: '11',
age: 10
},
{
name: '66',
age: 10
}
])
</script>
<template>
<ts :list="list2" > <!--传入数据列表-->
<h1>测试插槽</h1>
<template #col="{ item, index }"> <!--用解构的方式获取-->
序号:{{ index }}<br> <!--其实这里是循环-->
内容:{{ item }}
</template>
</ts>
</template>
UI库里的 table 组件一般都会支持这样的插槽,以便于灵活设置列表,比如 el-table 的 el-table-column:
(来自官网示例代码)
<el-table :data="tableData" style="width: 100%">
<el-table-column label="日期" width="180">
<template #default="scope">
<div style="display: flex; align-items: center">
<el-icon><timer /></el-icon>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</div>
</template>
</el-table-column>
...
</el-table>
这里的 default 就是一个匿名作用域插槽,可以通过scope.row
获得每一行的数据。
defineEmits
defineEmits 是定义事件的一种快捷表达方式,也是一种语法糖,这个和 defineModel 有重合的地方,那就是 v-model 的 update:modelValue
的部分。
话说,组件需要事件吗?以前是事件驱动,现在是数据驱动,或者说是状态驱动。以前监听事件,现在只需要监听状态的变化即可,从dom脱离出来。
好吧,其实我基本已经不使用 emit 了,感觉似乎并不需要了。
参考资料
1 Generic component enhancements - Discussion #436:
2 unplugin-vue-define-options - npm: https://www.npmjs.com/package/unplugin-vue-define-options
3 Announcing Vue 3.3 | The Vue Point: https://blog.vuejs.org/posts/vue-3-3
4 Vue 3.3 主要新特性详解 - 三咲智子 Kevin Deng: https://xlog.sxzz.moe/vue-3-3
6 官方帮助文档
Recommend
-
74
什么是Generic Host ? 这是在Asp.Net Core 2.1加入了一种新的Host,现在2.1版本的Asp.Net Core中,有了两种可用的Host。 Web Host –适用于托管W
-
27
-
39
-
42
watchOS 6 正式版来了,老款 Apple Watch 升级后表现如何?
-
16
从莫哈韦沙漠,再到卡塔利娜小岛,习惯以风景名胜作为 macOS 新系统命名的苹果,今年选择了美国加州西部的海岸线大索尔(Big Sur),开启了 Mac 新一年的篇章。 虽然命名的方式没有变化,但苹果强调,此次更新是「
-
19
北京时间 6 月 23 日凌晨 3 点,第一次线上 WWDC 的开幕 Keynote 正式结束,iOS 14 的第一个测试版也在不久后公布。许多开发者、爱好者都第一时间升级到最新系统准备尝...
-
3
免费体验!广告投放分析新功能,3 大突破,让 ROI 看得见! 神策小秘书...
-
12
在Golang的v1.17版本中,已经悄悄的加入了对泛型的支持; 在此之前,我们需要在.go2中尝试泛型,现在我们可以直接编写.go格式的文件,然后通过指定-gcflags=-G=3来编译含有泛型语法的源文件了; 同时,为了防止在体验时污染我们本地...
-
3
1. 泛型Generic 1.1 引入泛型:延迟声明 泛型方法声明时,并未写死类型,在调用的时候再指定类型。 延迟声明:推迟一切可以推迟的。 1.2 如何声明和使用泛型 泛型方法:方法名称后面加上尖括号,里面是...
-
5
A reusable generic autocomplete component for Blazor 17 November 2022 13:14 In
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK