前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots

Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots

作者头像
用户1174620
发布于 2023-10-16 08:23:54
发布于 2023-10-16 08:23:54
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

上一篇说了 DefineOptions、defineModel、Props 的响应式解构和从外部导入类型 这几个新功能,但是没有说Generic、defineSlots等,这是因为还没有完全搞清楚可以用在什么地方。折腾了几天终于弄清楚了。

这还要从 TS 的泛型说起。

泛型的目的和意义

泛型仅仅只是表达传啥都行吗?当然不是,因为js原生就支持“泛型”,本来就啥都可以传的。 泛型的目的是——约束!泛型相当于制定了一个白名单,名单里面的类型可以传,不在名单里面的不可以传。

TS 的泛型可以帮助我们更准确的推断类型,从而在编写代码的时候,可以有更准确的提示和提供验证依据。

泛型组件(Generic Component)

组件的props可以设置各种类型,那么如果想用泛型的话,要如何设置呢?这就需要使用 Generic:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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把数组元素传递给父组件:(好像有点绕)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <!--匿名插槽-->
  <slot></slot>
  <div v-for="(item, index) in list" :key="index">
    <!--作用域插槽-->
    <slot name="col" :row="item" :index="index" ></slot>
  </div>
</template>

父组件里使用的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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>
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <ts :list="list2" > <!--传入数据列表-->
    <h1>测试插槽</h1>
    <template #col="{ item, index }"> <!--用解构的方式获取-->
      序号:{{ index }}<br> <!--其实这里是循环-->
      内容:{{ item }}
    </template>
  </ts>
</template>

UI库里的 table 组件一般都会支持这样的插槽,以便于灵活设置列表,比如 el-table 的 el-table-column:

(来自官网示例代码)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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 了,感觉似乎并不需要了。

参考资料

Generic component enhancements - Discussion #436:

unplugin-vue-define-options - npm: https://www.npmjs.com/package/unplugin-vue-define-options

Announcing Vue 3.3 | The Vue Point: https://blog.vuejs.org/posts/vue-3-3

Vue 3.3 主要新特性详解 - 三咲智子 Kevin Deng: https://xlog.sxzz.moe/vue-3-3

5 Vue3.3 发布:十分钟速递

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
🎉一个demo体验Vue3.3+TypeScript所有新功能🎉
由于最新的功能defineModel是实验特性,需要在vite.config.js里开启,另外需要开启解构props响应式功能
萌萌哒草头将军
2023/06/18
5940
🎉一个demo体验Vue3.3+TypeScript所有新功能🎉
Vue3.3 的新功能的一些体验
先来一个简单的,以前我们有时候想设个name,有时候不想让组件自动继承属性,这时候需要单独设置一个script进行设置,现在简化了操作,直接使用 defineOptions 即可。
用户1174620
2023/10/16
5170
通过UI库深入了解Vue的插槽的使用技巧
父子组件传值可以通过 prosp + emit 来实现,虽然 props 可以传递各种类型,但是却不能传递组件(包括HTML),这样灵活度就差了一些。 那么怎么办呢?为了提高灵活性,Vue 提供了插槽功能。
用户1174620
2022/05/09
1.5K0
通过UI库深入了解Vue的插槽的使用技巧
【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现
如果基于原生HTML来实现显示数据列表的功能的话,那么需考虑如何创建 table,如何设置css等。 如果直接使用UI库的话,那么可以简单很多,只需要设置各种属性,然后绑定数据即可。 以 el-table 为例:
用户1174620
2022/06/12
1.8K0
【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现
前端系列15集-watch,watchEffect,eventBus
watchEffect,它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
达达前端
2023/10/08
5240
Vue3 除了 keep-alive,还有哪些页面缓存的实现方案
有这么一个需求:列表页进入详情页后,切换回列表页,需要对列表页进行缓存,如果从首页进入列表页,就要重新加载列表页。
winty
2024/04/30
7020
Vue3 除了 keep-alive,还有哪些页面缓存的实现方案
全面了解 Vue.js 函数式组件
如果你是一位前端开发者,又在某些机会下阅读过一些 Java 代码,可能会在后者中看到一种类似 ES6 语法中箭头函数的写法
江米小枣
2021/11/02
2.9K0
关于 Vue3 + setup + ts 使用技巧的总结
ref 一般用于基本的数据类型,比如 string,boolean ,reactive 一般用于对象 ref 的地方其实也是调用的 reactive 实现的。
前端达人
2023/08/31
1.1K0
关于 Vue3 + setup + ts 使用技巧的总结
前端系列14集-Vue3-setup
页面浏览量(Page View,PV)和访客数(Unique Visitors,UV)
达达前端
2023/10/08
5060
前端系列14集-Vue3-setup
后台数据管理系统 - 项目架构设计【黑马程序员】
在线演示:https://fe-bigevent-web.itheima.net/login
HelloWorldZ
2024/03/20
1.3K0
后台数据管理系统 - 项目架构设计【黑马程序员】
Vue.js 的一些小技巧
比如一个 <my-button> 上暴露了一个 width 属性,我们既可以传 100px,也可以传 100 :
步履不停凡
2019/09/11
8100
Vue3 script-setup 使用指南
本文主要是讲解 <script setup> 与 TypeScript 的基本使用。
ConardLi
2022/02/18
5.8K0
Vue3 过10种组件通讯方式
众所周知,Vue.js 中一个很重要的知识点是组件通信,不管是业务类的开发还是组件库开发,都有各自的通讯方法。
德育处主任
2022/04/17
2K0
Vue3 过10种组件通讯方式
初识 vue3 之单文件组件 script setup
<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 <script> 语法,它具有更多优势:
Qwe7
2022/01/30
1.8K0
【Vue.js——ElementUi】element-ui 组件二次封装(蓝桥杯真题-2276)【合集】
element-ui 官网上具有单选功能的表格 demo 为:点击表格下方的按钮可以选中指定的某行数据。效果如下:
Rossy Yan
2025/01/24
1570
【Vue.js——ElementUi】element-ui 组件二次封装(蓝桥杯真题-2276)【合集】
Vue3学习笔记
setup等同于原data,通过reactive定义变量病赋值到data,再return出去,就可以在template用双大括号使用,计算特性:doublecounter的定义,注意需要import computed
kif
2023/03/10
1.2K0
【项目总结】vue3-shop-cms
在完成基于 Vue3 和 TypeScript 的商城后台管理系统项目后,总结的学习笔记。项目原作者coderwhy
客怎眠qvq
2022/11/01
6870
【项目总结】vue3-shop-cms
Vue 3 组件通信方式总结
子组件接收父级自定义属性则与vue2不同,vue2中是以props 配置项来接收,vue3 中则需要 用到宏函数 defineProps类接收
iwhao
2024/07/24
2830
vue插槽slot、slot-scope、v-slot的区别以及嵌套插槽的使用
slot 在英语中作为名词时表示:(可投入东西的)狭长孔,狭槽;(在一系列事件中为某事安排的)时间,空档;(组织、团体等中的)位置,职位。
人人都是码农
2024/01/23
6.7K0
vue插槽slot、slot-scope、v-slot的区别以及嵌套插槽的使用
Vue3 中 使用 TypeScript
在单文件组件中使用 TypeScript,需要在 <script> 标签上加上 lang="ts" 的 attribute。当 lang="ts" 存在时,所有的模板内表达式都将享受到更严格的类型检查
程序员海军
2023/11/05
7150
相关推荐
🎉一个demo体验Vue3.3+TypeScript所有新功能🎉
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验