Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots
2023/5/26 18:22:45
本文主要是介绍Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
上一篇说了 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
5 Vue3.3 发布:十分钟速递
6 官方帮助文档
7 elementPlus
这篇关于Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-04React 19 来了!新的编译器简直太棒了!
- 2025-01-032025年Node.js与PHP大比拼:挑选最适合的后端技术进行现代web开发
- 2025-01-03?? 用 Gemini API、Next.js 和 TailwindCSS 快速搭建 AI 推文生成项目 ??
- 2024-12-31Vue CLI多环境配置学习入门
- 2024-12-31Vue CLI学习入门:一步一步搭建你的第一个Vue项目
- 2024-12-31Vue3公共组件学习入门:从零开始搭建实用组件库
- 2024-12-31Vue3公共组件学习入门教程
- 2024-12-31Vue3学习入门:新手必读教程
- 2024-12-31Vue3学习入门:初学者必备指南
- 2024-12-30Vue CLI多环境配置教程:轻松入门指南