Vue 3.3 新特性前瞻和简单评价

更新日期: 2023-05-06阅读: 1.2k标签: Vue3

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


泛型组件支持

vue一直以来都是没办法很好的实现泛型组件,终于在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年过去了,不过大部分开发者都有使用一些社区插件来达到这个用法,现在官方终于提供了,在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带来新的工具

这是来自智子君的新特性,可以在<script setup/>中使用defineModel和非<script setup/>中使用的useModel工具

// 默认的model (通过 `v-model`)
const modelValue = defineModel()
   // ^? Ref<any>
modelValue.value = 10

const modelValue = defineModel<string>() //增加类型
   // ^? Ref<string | undefined>
modelValue.value = "hello"

// 带有设置的默认model, 要求非undefined 
const modelValue = defineModel<string>({ required: true })
   // ^? Ref<string>

// 特定名称的model (通过 `v-model:count` )
const count = defineModel<number>('count')
count.value++

// 具有默认值的特定名称的model
const count = defineModel<number>('count', { default: 0 })
   // ^? Ref<number>

// 本地作用域可变的 model, 顾名思义
// 可以不需要父组件传递v-model
const count = defineModel<number>('count', { local: true, default: 0 })

还有useModel作为非<script setup/>中使用的工具

import { useModel } from 'vue'

export default {
  props: {
    modelValue: { type: Number, default: 0 },
  },
  emits: ['update:modelValue'],
  setup(props) {
    const modelValue = useModel(props, 'modelValue')
       // ^? Ref<number>

    return { modelValue }
  }
}
评价: 又一提升DX的利器,定义一个v-model的属性确实比较繁琐,而且在sfc内实用性不强,一般需要搭配vueuse/useVModels使用,官方加入这个宏和工具函数确实是很不错


defineOptions

又是智子君的pr,早前来自RFC,这个内容的话应该不少人都在Vue Macro中用过了

本来Vue如果你需要在<script setup>中定义一些原先Option api的属性比如inheritAttrs/name是需要创建一个<script>单独导出这两个属性的,现在有了defineOptions就可以省去这一步骤

<script setup>
// 一些代码
</script>
<script>
export default {
  name: "ComponentName"
}
</script> 
<script setup>
defineOptions({
  name: "ComponentName"
})
// 一些代码
</script> 
评价: 这个特性可以在Vue Macro使用到,先行体验,反正我是用上了很爽


defineSlots 宏以及 slots 属性

还是来自智子君,TQL

允许定义slots的具体类型,首先是新增了一个SlotsType以及slots属性可以options api中使用

import { SlotsType } from 'vue'

export default defineComponent({
  slots: Object as SlotsType<{
    default: { foo: string; bar: number }
    item: { data: number }
  }>,
  setup(props, { slots }) {
    expectType<undefined | ((scope: { foo: string; bar: number }) => any)>(
      slots.default
    )
    expectType<undefined | ((scope: { data: number }) => any)>(slots.item)
  }
})

对于这个定义的组件SlotComponent,再组件中使用的话就是

<template>
  <SlotComponent>
    <template #default="{ foo, bar }">
      {{ foo }} is string,{{ bar }} is number
    </template>
    <template #item="{ data }">
      {{ data }} is number
    </template>
  </SlotComponent>
</template>

defineSlots和slots属性类似,不过提供一个函数语法

// 与 对象语法表现一致,谢谢ES没有将default当属性关键词 可喜可贺可喜可贺
const slots = defineSlots<{
  default(props: { foo: string; bar: number }): any // or VNode[]
}>()
评价: slot有正确的类型的话对于组件库来说是一个挺好的消息,毕竟从引入scopeSlot到现在用户都不能很好地确定自己该怎么用某个scopeSlot


模板中使用 console.log

突然的调试可能会用到的console.log但是在模板中不好使,现在3.3加上了额外支持,不需要再自己为模板作用域增加一个函数来打印东西了

评价: 无伤大雅,提升DX,偶尔会用到会感觉很舒服


不太重要的特性

对Suspense的改进

个人觉得vue的<Suspense>可以暂时不用关注,实验性特性好久了,pr在这里

废弃和修改的特性

v-is 指令废弃

废弃v-is了,全部改用:is指令(好奇真的有人还在用这个指令吗?)

app.config.unwrapInjectedRef

app.config.unwrapInjectedRef这个属性没了,在3.3会默认对使用Option api的inject属性进行注入的ref进行拆包,

vnode hook 废弃

vnode hook 应该用户比较少,就是有一个@vnode-*的指令变成了@vue:*,这个特性应该蛮少用的,甚至连网上都没有什么介绍,好像是为Vnode的生命周期提供一些类似与组件生命周期的功能,不知道有没有清楚这个特性能干吗的伙伴介绍下。


对于生态开发者的改进

app.runWithContext()

在App上增加了一个runWithContext()可以用于确保对应用程序级别的全局变量存在,比如通过provide的各个值,可以用于改进vue生态的各个包,pinia/vue-router之类的

const app = createApp(App)

app.provide('foo', 1)

app.runWithContext(() => inject('foo')) // should return 1

hasInjectionContext

hasInjectionContext这是面向基于vue的库作者用于检查是否可以使用inject()的工具,如果当前环境可以使用就返回true,不可以的环境其实就是setup外了,库作者使用该函数可以省去额外对当前环境的检测。

评价: 这些对生态开发者来说比较有用的功能,如果有写库的小伙伴可以注意一下


需要注意的

对于TSX用户,vue3.3不在默认注册全局JSX命名空间,需要手动在tsconfig.json中修改jsxImportSource或者使用魔法注释/* @jsxImportSource vue */这是避免全局jsx类型冲突。

来源:https://enpitsulin.xyz/blog/new-feature-preview-vue-33

链接: https://fly63.com/article/detial/12469

vue3.x 新特性 - CompositionAPI

安装 vue-cli3,在使用任何 @vue/composition-api 提供的能力前,必须先通过 Vue.use() 进行安装,安装插件后,您就可以使用新的 Composition API 来开发组件了。

Vue3数据响应系统

Vue3 就是基于 Proxy 对其数据响应系统进行了重写,现在这部分可以作为独立的模块配合其他框架使用。数据响应可分为三个阶段: 初始化阶段 --> 依赖收集阶段 --> 数据响应阶段

快速进阶Vue3.0

在2019.10.5日发布了Vue3.0预览版源码,但是预计最早需要等到 2020 年第一季度才有可能发布 3.0 正式版。新版Vue 3.0计划并已实现的主要架构改进和新功能:

Vue 3 对 Web 应用性能的改进

有关即将发布的 Vue.js 的第 3 个主要版本的信息越来越多。通过下面的讨论,虽然还不能完全确定其所有内容,但是我们可以放心地认为,它将是对当前版本(已经非常出色)的巨大改进。 Vue 团队在改进框架 API 方面做得非常出色

Vue3 中令人兴奋的新功能

用新的 Vue 3 编写的程序效果会很好,但性能并不是最重要的部分。对开发人员而言,最重要的是新版本将会怎样影响我们编写代码的方式。如你所料,Vue 3 带来了许多令人兴奋的新功能。值得庆幸的是

200 行从零实现 vue3

emmm 用半天时间捋顺了 vue3 的源码,再用半天时间写了个 mini 版……我觉得我也是没谁了,vue3 的源码未来一定会烂大街的,我们越早的去复现它,就……emm可以越早的装逼hhh

从 Proxy 到 Vue 源码,深入理解 Vue 3.0 响应系统

10 月 5 日,尤雨溪在 GitHub 开放了 Vue 3.0 处于 pre-alpha 状态的源码,这次 Vue 3.0 Updates 版本的更新,将带来五项重大改进:速度体积、可维护性、面向原生、易用性

Vue 的数据响应式(Vue2 及 Vue3)

从一开始使用 Vue 时,对于之前的 jq 开发而言,一个很大的区别就是基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom。换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改。

在Vue2与Vue3中构建相同的组件

Vue 开发团队终于在今天发布了 3.0-beta.1 版本,也就是测试版。通常来说,从测试版到正式版,只会修复 bug,不会引入新功能,或者删改老功能。所以,如果你对新版本非常感兴趣,或者有新项目即将上马,不妨尝试一下新版本

Vue3中的Vue Router初探

对于大多数单页应用程序而言,管理路由是一项必不可少的功能。随着新版本的Vue Router处于Alpha阶段,我们已经可以开始查看下一个版本的Vue中它是如何工作的。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!