Vue3.3发布了,有啥新特性?简单的了解下

共 9129字,需浏览 19分钟

 ·

2023-06-02 09:13

09237cb5f27312375933fc1595ef4b8e.webp

前言

虽然3.3当前还处于beta阶段但是其带来的一些特性十分激动人心,就在这里简单的给大家带来新特性的前瞻,为以后的升级做做准备😁

泛型组件支持

Vue一直以来[1]都是没办法很好的实现泛型组件,终于在3.3版本增加了这一功能

首先是面向TSX用户为defineComponent 工具函数增加了泛型支持,当参数传入一个泛型函数时类型会提示正常,比如我们可以基于这个特性使用tsx简单构造一个表格组件

      
        import { defineComponent } from 'vue';
      
      
        
          
type Props<T> = { data: T[]; columns: { label: string; field: keyof T }[] };
const Table = defineComponent(<T,>(props: Props<T>) => { return () => ( <table> <thead> <tr> {props.columns?.map((item) => ( <th>{item.label}th> ))} tr> thead> <tbody> {props.data?.map((row) => props.columns?.map((column) => <td>{row[column.field]}td>) )} tbody> table> ); });
export default Object.assign(Table, { name: 'GenericsTableTsx', props: ['columns', 'data'] });

但是值得注意的是我们仍需要为这个组件传入props属性,否则在使用的时候会将应该是props的的属性挂载到$attrs上,这点其实基本上杜绝了这样的用法,所以说仅仅只是类型正确,不太推荐生产用这样的方法构建泛型组件。

SFC泛型组件支持

其实上面的功能还是为了铺垫这个,我们了解怎么用SFC来复现上面的组件

      
        
          <template>
        
      
      
          <table>
      
      
            <thead>
      
      
              <tr>
      
      
                <th v-for="item in columns">
      
      
                  <slot name="header-cell" v-bind="{ label: item.label }">
      
      
                    {{ item.label }}
      
      
                  slot>
      
      
                th>
      
      
              tr>
      
      
            thead>
      
      
            <tbody>
      
      
              <tr v-for="row in data">
      
      
                <td v-for="column in columns">
      
      
                  <slot name="cell" v-bind="{ data: row[column.field] }">
      
      
                    {{ row[column.field] }}
      
      
                  slot>
      
      
                td>
      
      
              tr>
      
      
            tbody>
      
      
          table>
      
      
        
          template>
        
      
      
        
          <script setup lang="ts" generic="T">
        
      
      
          const { columns, data } = defineProps<{
      
      
            data: T[];
      
      
            columns: {
      
      
              label: string;
      
      
              field: keyof T;
      
      
            }[];
      
      
          }>();
      
      
        
          script>
        
      
    

Vue@3.3为script增加了一个属性generic用于创建泛型参数,多个参数当然也像是ts中使用,隔开。

评价: 很强的新特性,vue终于有泛型组件了真的是可喜可贺,就是对于TSX的支持还是需要额外增加props属性比较麻烦,这个问题也是比较久远的了,希望vue团队以后在为TSX的开发体验提升上努努力

defineProps 宏支持引入的类型

这个需求[2]已经2年过去了,不过大部分开发者都有使用一些社区插件来达到这个用法,现在官方终于提供了,在3.3我们可以轻松的使用外部导入的类型创建Props

      
        
          <script setup lang="ts">
        
      
      
        import type { SomeType } from 'some-where'
      
      
        
          
const props = defineProps<{ data: SomeType }>() script>

评价: 众望所归,更方便的管理在Vue项目中的类型,不需要再在SFC中写又臭又长的类型体操了

defineEmits 宏更简便的写法

对于3.2,defineEmits基于泛型需要这样使用

      
        defineEmits<{
      
      
          (e: 'foo', id: string): void
      
      
          (e: 'bar',...args: any[]): void
      
      
        }>()
      
      
        
          

3.3的写法,对于单个参数使用具名元组的方式定义,如果使用rest params的参数可以直接使用T[]来解决

      
        defineEmits<{
      
      
          foo: [id: string]
      
      
          bar: any[]
      
      
        }>()
      
      
        
          

评价: 提升DX的小功能,函数重载的形式写起太多的emits确实有点烦人

为v-model带来新的工具

这是来自智子君[3]的新特性[4],可以在