2020 年 4 月 16 日,前端业内最知名的框架之一——vue——发布了大版本 3.0 的第一个 beta 版本,增加了许多新特性、新功能,并进一步对性能进行了优化,让我们来看看都有哪些激动人心的变化
提案概览
本篇——Vue
性能优化
- 以更高性能的方式提供本机自定义元素支持.rfc
API 改动
- 新增了内置指令
v-slot,将slot与slot-scope进行整合.rfc - 原本位于
this上的实例属性(如this.$nextTick)被转变为全局 api,用以实现 tree-shaking 优化.rfc - 组件
render方法的参数h或createElement被转变为全局 api,且h函数接收与 React 相同的 3 个参数.rfc - 原本位于 Vue 类上的
静态属性被转移至 Vue 实例的成员属性.rfc - 针对自定义组件的
v-model需要带有参数使用,并且需要通过触发特定格式的事件名来完成数据更新.rfc - 自定义指令的 API 命名设计更贴近生命周期的规则.rfc
transition组件作为自定义组件的 root 时,从外部切换组件不会触发过渡效果.rfctransition组件的v-enter和v-leave类名被重命名为v-enter-from和v-leave-from.rfc- 带有
scope作用域的组件样式从>>>和/deep/的语法转变为更丰富的自定义扩展方式.rfc - 删除枚举属性的内部概念,并将这些属性与普通的非布尔属性相同(纯翻译,不太理解).rfc
新特性、新功能
- 简化
v-slot的书写语法,提供了#符号用于标识插槽.rfc - 指令的参数支持动态数据,如
@[event]="handler".rfc - 内置了
defineAsyncComponentapi,用于创建异步组件.rfc1.rfc2 - 支持以
纯函数的形式编写函数组件,且函数组件的参数与setupapi 的参数相同——props与包含slots、attrs和emit的context.rfc - 新的逻辑复用方式——Composition API.rfc与文档
- 新增了核心组件
teleport,效果与 React 的Portals类似,可以将子节点渲染到存在于父组件以外的 DOM 节点.rfc - 可以明确声明自定义组件具有的事件.rfc
被废弃的功能
v-bind的sync修饰符被移除,并以参数形式作为v-model的扩展.rfcthis.$scopedSlots被移除.rfc- 自定义组件上的
{ functional: true }选项以及<template functional>被移除.rfc - 自定义组件上的
{model: {prop: String, event: String }}被移除.rfc - 使用
keyCodes用于修饰事件的写法被移除,并且不再支持config.keyCodes这一全局配置.rfc - 过滤器
filter从独立的语法模式中被移除.rfc - 内联模板
inline-template属性被移除.rfc - 自定义组件
data属性的对象写法被移除,现在仅支持函数写法.rfc - 组件实例的事件 api
$on、$off和$once被移除.rfc
番外之 Vue-Router
router-link组件的tag和event属性被移除,同时新增了custom属性和对scoped-slot的支持.rfc- 路由配置中增加了
meta属性,用以描述元数据.rfc - 更改应用 router-link-active 的方式,使其与路由器概念更加一致.rfc
- 允许在路由器工作时添加和删除路由配置.rfc
- 明确定义什么是导航失败,以及如何以及在何处捕获它们.rfc
番外之 Vue Test Utils
- 支持等待异步 Rerender 完成后断言.rfc
核心新特性——Composition API
Introducing the Composition API: a set of additive, function-based APIs that allow flexible composition of component logic.
根据 Vue 官方对 Composition API 的定义,这是一组用于组合组件逻辑,实现逻辑复用的函数式 API,与之相类似并且经常被拿来比较的则是React于 16.8 版本 推出的Hook特性。
1 | import { reactive, unref, watchEffect, toRef } from "vue"; |
以上是一个简单的可以用于 input 等表单组件进行状态及逻辑复用的自定义 Composition,它定义了包含innerValue属性的state,并监听了传入参数的value属性的变化并对 state 进行自动更新,同时创建了一个用于修改 state 的函数handleChange,并在函数的结尾处将innerValue与handleChange暴露给使用这个自定义 Composition 的组件,实现不同表单组件间的逻辑复用
而 CompositionAPI 与 ReactHook 在实现上,也完美体现了所在框架的设计思想与理念的差异:
- CompositionAPI 以语义的形式定义 API,如
computed、watch和onMounted;而 ReactHook 的命名更通用,如useMemo和useEffect。 - CompositionAPI 能够进行自动化的依赖收集;而 ReactHook 则需要手动设置依赖,如
useEffect和useMemo可以提供第二个参数作为callback的依赖项。 - Composition 的
watchEffect等 api 可以被其他生命周期钩子包裹;而 ReactHook 的useEffect(包括其他 api)必须位于函数的最外层,且不能存在逻辑分支。 - CompositionAPI 的
setup方法只会在初始化时(节点在beforeCreate之前)执行一次;而 ReactHook 的 api 则会在每次函数组件 ReRender 时都执行。 - 位于
setup方法内部的 CompositionAPI,若初始化后需要响应数据变化而自动触发,需要以reference的形式传递;ReactHook 的参数在大多数情况下都是以plain object的形式传递
以上种种差异,也使得两种特性虽然都是基于函数式的理念而产生的,都是为了实现组件间的逻辑复用,但在具体应用实践中出现诸多不同之处,需要开发者仔细区分、分别掌握其细(坑)节(点)。
由于 Vue3 在底层模板解析编译的处理上与 2.x 有较大的差异,现有的编译、测试工具及 CLI 脚手架都无法用于 3.0 的项目,因此尤大特地写了一个用于开发快速原因的小工具Vite。目前我们通过这个工具对 vue3 进行抢先体验。
同时笔者在参考了react-hooks-testing-library的实现思路后,简单开发了一个可用于测试自定义 Composition 的小工具test-vue-composition-utils