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 - 内置了
defineAsyncComponent
api,用于创建异步组件.rfc1.rfc2 - 支持以
纯函数
的形式编写函数组件,且函数组件的参数与setup
api 的参数相同——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