上一篇说了 DefineOptions、defineModel、Props 的响应式解构和从外部导入类型 这几个新功能,但是没有说Generic、defineSlots等,这是因为还没有完全搞清楚可以用在什么地方。折腾了几天终于弄清楚了。
这还要从 TS 的泛型说起。
泛型的目的和意义
泛型仅仅只是表达传啥都行吗?当然不是,因为js原生就支持“泛型”,本来就啥都可以传的。
泛型的目的是——约束!泛型相当于制定了一个白名单,名单里面的类型可以传,不在名单里面的不可以传。
TS 的泛型可以帮助我们更准确的推断类型,从而在编写代码的时候,可以有更准确的提示和提供验证依据。
泛型组件(Generic Component)
组件的props可以设置各种类型,那么如果想用泛型的话,要如何设置呢?这就需要使用 Generic:
<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 官方帮助文档