人机交互爱好者的随笔

0%

Vue新版本前瞻(1)

2020 年 4 月 16 日,前端业内最知名的框架之一——vue——发布了大版本 3.0 的第一个 beta 版本,增加了许多新特性、新功能,并进一步对性能进行了优化,让我们来看看都有哪些激动人心的变化

提案概览

本篇——Vue

性能优化

  1. 以更高性能的方式提供本机自定义元素支持.rfc

API 改动

  1. 新增了内置指令v-slot,将slotslot-scope进行整合.rfc
  2. 原本位于this上的实例属性(如this.$nextTick)被转变为全局 api,用以实现 tree-shaking 优化.rfc
  3. 组件render方法的参数hcreateElement被转变为全局 api,且h函数接收与 React 相同的 3 个参数.rfc
  4. 原本位于 Vue 类上的静态属性被转移至 Vue 实例的成员属性.rfc
  5. 针对自定义组件的v-model需要带有参数使用,并且需要通过触发特定格式的事件名来完成数据更新.rfc
  6. 自定义指令的 API 命名设计更贴近生命周期的规则.rfc
  7. transition组件作为自定义组件的 root 时,从外部切换组件不会触发过渡效果.rfc
  8. transition组件的v-enterv-leave类名被重命名为v-enter-fromv-leave-from.rfc
  9. 带有scope作用域的组件样式从>>>/deep/的语法转变为更丰富的自定义扩展方式.rfc
  10. 删除枚举属性的内部概念,并将这些属性与普通的非布尔属性相同(纯翻译,不太理解).rfc

新特性、新功能

  1. 简化v-slot的书写语法,提供了#符号用于标识插槽.rfc
  2. 指令的参数支持动态数据,如@[event]="handler".rfc
  3. 内置了defineAsyncComponentapi,用于创建异步组件.rfc1.rfc2
  4. 支持以纯函数的形式编写函数组件,且函数组件的参数与setupapi 的参数相同——props与包含slotsattrsemitcontext.rfc
  5. 新的逻辑复用方式——Composition API.rfc文档
  6. 新增了核心组件teleport,效果与 React 的Portals类似,可以将子节点渲染到存在于父组件以外的 DOM 节点.rfc
  7. 可以明确声明自定义组件具有的事件.rfc

被废弃的功能

  1. v-bindsync修饰符被移除,并以参数形式作为v-model的扩展.rfc
  2. this.$scopedSlots被移除.rfc
  3. 自定义组件上的{ functional: true }选项以及<template functional>被移除.rfc
  4. 自定义组件上的{model: {prop: String, event: String }}被移除.rfc
  5. 使用keyCodes用于修饰事件的写法被移除,并且不再支持config.keyCodes这一全局配置.rfc
  6. 过滤器filter从独立的语法模式中被移除.rfc
  7. 内联模板inline-template属性被移除.rfc
  8. 自定义组件data属性的对象写法被移除,现在仅支持函数写法.rfc
  9. 组件实例的事件 api$on$off$once被移除.rfc

番外之 Vue-Router

  1. router-link组件的tagevent属性被移除,同时新增了custom属性和对scoped-slot的支持.rfc
  2. 路由配置中增加了meta属性,用以描述元数据.rfc
  3. 更改应用 router-link-active 的方式,使其与路由器概念更加一致.rfc
  4. 允许在路由器工作时添加和删除路由配置.rfc
  5. 明确定义什么是导航失败,以及如何以及在何处捕获它们.rfc

番外之 Vue Test Utils

  1. 支持等待异步 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { reactive, unref, watchEffect, toRef } from "vue";

export function useValue(params = {}) {
const state = reactive({
innerValue: unref(params.value) || unref(params.defaultValue),
});
watchEffect(() => {
if (unref(params.value) != undefined) {
state.innerValue = unref(params.value);
}
});
const handleChange = (value) => {
state.innerValue = value;
};
return {
innerValue: toRef(state, "innerValue"),
onChange: handleChange,
};
}

以上是一个简单的可以用于 input 等表单组件进行状态及逻辑复用的自定义 Composition,它定义了包含innerValue属性的state,并监听了传入参数的value属性的变化并对 state 进行自动更新,同时创建了一个用于修改 state 的函数handleChange,并在函数的结尾处将innerValuehandleChange暴露给使用这个自定义 Composition 的组件,实现不同表单组件间的逻辑复用

而 CompositionAPI 与 ReactHook 在实现上,也完美体现了所在框架的设计思想与理念的差异:

  1. CompositionAPI 以语义的形式定义 API,如computedwatchonMounted;而 ReactHook 的命名更通用,如useMemouseEffect
  2. CompositionAPI 能够进行自动化的依赖收集;而 ReactHook 则需要手动设置依赖,如useEffectuseMemo可以提供第二个参数作为callback的依赖项。
  3. Composition 的watchEffect等 api 可以被其他生命周期钩子包裹;而 ReactHook 的useEffect(包括其他 api)必须位于函数的最外层,且不能存在逻辑分支。
  4. CompositionAPI 的setup方法只会在初始化时(节点在beforeCreate之前)执行一次;而 ReactHook 的 api 则会在每次函数组件 ReRender 时都执行。
  5. 位于setup方法内部的 CompositionAPI,若初始化后需要响应数据变化而自动触发,需要以reference的形式传递;ReactHook 的参数在大多数情况下都是以plain object的形式传递

以上种种差异,也使得两种特性虽然都是基于函数式的理念而产生的,都是为了实现组件间的逻辑复用,但在具体应用实践中出现诸多不同之处,需要开发者仔细区分、分别掌握其细(坑)节(点)。

由于 Vue3 在底层模板解析编译的处理上与 2.x 有较大的差异,现有的编译、测试工具及 CLI 脚手架都无法用于 3.0 的项目,因此尤大特地写了一个用于开发快速原因的小工具Vite。目前我们通过这个工具对 vue3 进行抢先体验。

同时笔者在参考了react-hooks-testing-library的实现思路后,简单开发了一个可用于测试自定义 Composition 的小工具test-vue-composition-utils

引用

  1. 抄笔记:尤雨溪在 Vue3.0 Beta 直播里聊到了这些
  2. Vue3模板编译编辑器