前言
由于笔者最近试玩了一下供 vue2.x 版本里享受 vue3.x 开发体验的 @vue/composition-api,看到它的代码量才一千多行,很适合用来快速学习 vue3 一些新 api 的用法,和背后的思想。过完一遍后对阅读 vue-next 也很有帮助,所以有了以下这篇文章。
建议
在阅读前或者阅读过程中,可以用 vue-cli 新建一个 vue 项目,装一个compositon api玩一下。
视频参考:www.bilibili.com/video/av873… (我也是看了这个视频才开始试玩 composition api 的)
api参考:github.com/vuejs/compo…
RFC参考:composition-api.vuejs.org/#summary
正文
ps. 下列源码路径参考截图最上方,观众老爷们自行查找
1. createComponet/defineComponent

export default defineComponent({}) 是等价于export default {} 的
那为什么要另外定义一个这样的 API 呢

2. setup(props)
所以setup是什么呢?
正如起名 setup 是一个初始化函数。它是一个接受 props(这里的 props 正是 defineComponent 所传的 props) 作为参数被调用于 beforeCreate 的函数。会返回一个对象,或者函数。

setup(props) {
return {}
}
3. reactive(obj)
这里可以理解为 reactive 就是 vue2 里面的 data。传入一个对象,然后通过 observe 函数让 obj 可观察。


ps. 这里复习一下:Vue.observable 是 vue 2.6 的 api
它会调用 observe 函数,并返回该对象。


Vue-next

4. reactivity api
这里包括了 ref(raw), computed(options), watch(source, cb, options) 三个 API ,因为它的设计与 react Hooks 很相似,所以也是被讨论的最多的 api。
这里提出的 API 和 React Hooks 有一定的相似性,具有同等的基于函数抽取和复用逻辑的能力,但也有很本质的区别。React Hooks 在每次组件渲染时都会调用,通过隐式地将状态挂载在当前的内部组件节点上,在下一次渲染时根据调用顺序取出。而 Vue 的 setup() 每个组件实例只会在初始化时调用一次 ,状态通过引用储存在 setup() 的闭包内。
⬆️ 尤大在 Vue Function-based API RFC 上的原话
ref(raw)
对标 vue2 里面 data 的单个参数(或者 react hooks 的useState) 函数传入一个 any 的参数 raw,通过调用上述 reactive(obj) 生成一个被监听对象,用于存储 raw。

computed(options) -> option = {get, set}
对标vue2里面的 computed, 返回一个 ref


ps. 吐槽一下,computed 明明 type 是 readonly 但看源码它是有开放 设置 setter 的钩子的,如果 options 传入是一个 { set: () => {}, get => {}}。
当然这样写在你对 computed 生成的 ref 赋值时,依然是不会奏效的…毕竟 vue2 的 computed 已经把 setter 禁掉了。
watch(source, cb, options)
对标 vue2 里面的 watch。有点不一样的是,watch 第一个参数 source 它可以是: 一个返回任意值的函数 一个包装对象 一个包含上述两种数据源的数组, 第二个参数 cb 是一个回调函数。 第三个参数 options

和 2.x 的
$watch有所不同的是,watch()的回调会在创建时就执行一次。这有点类似 2.x watcher 的immediate: true选项,但有一个重要的不同:默认情况下watch()的回调总是会在当前的 renderer flush 之后才被调用 —— 换句话说,watch()的回调在触发时,DOM 总是会在一个已经被更新过的状态下。 这个行为是可以通过选项来定制的。
在 2.x 的代码中,我们经常会遇到同一份逻辑需要在 mounted 和一个 watcher 的回调中执行(比如根据当前的 id 抓取数据),3.0 的
watch()默认行为可以直接表达这样的需求。
来看看它是怎么实现上面逻辑的:

watcher.update() ,它不是马上执行callback的,而是把它推送到一个队列里,等 nextTick 后才真正执行这个callback。
新增 flush option 用来定制 cb 在更新前还是更新后触发,分为 pre | post | sync 三种状态 如果为 sync 会触发 vue2.x 里的隐藏 option -> sync : true

如果你想在 renderer flush 之前调用可以把 flush 设置为 pre

5. 生命周期
剩下的是API 基本都是生命周期的勾子了。通过 vue.config.optionMergeStrategies 把 callback 合并到当前对应的生命周期内。

结尾
Composition api 的 api 与源码解析就讲到这里了。可能存在不少错漏,欢迎大家指导。