在Vue2.0中,我们通过组件对象的data属性来传入一个返回对象的函数,经Vue的处理即可得到响应式对象。而在Vue3.0当中,这个过程被提取为 Reactivity API ,可由用户手动调用。
reactive
这个API以对象作为参数,返回一个响应式的对象。
由于Vue3.0使用了Proxy作为数据劫持的方式,所以向响应式对象直接添加属性会立刻被Vue3.0跟踪,无需像2.0中那样使用 Vue.set 方法来使特定属性响应式化。
这个API值得注意的是不能直接使用解构赋值来获取其属性,得到的变量不会是响应式的,需要通过 toRefs 进行转换才能进行解构赋值。
ref
此API可接收基础类型值作为参数,并将此值响应式化。
对于ref值,需要使用 .value 的方法来访问其值,如果接受一个对象,则其 .value 的值与直接传给reactive所得到的结果一致。
ref的自动展开
ref自动展开的情况有两个:
- 如果使用vue模板,则ref的值可以不需要使用
.value进行访问。 - 如果ref是作为
reactive对象的属性值,那么通过相关属性也无需.value进行访问(注意这对其余reactive引用类型不适用,如Array,Map等等)**readonly
readonly可以接受一个reactive或者ref作为参数,返回一个无法修改的reactive或ref。
这相当于给原来的reactive或ref套了一层readonly的壳,通过这个返回值是无法进行修改操作,但readonly的值仍然与其参数进行同步。下面代码中 b.x 的变化会同时反映到 c.x 身上:
import {reactive, readonly} from '@vue/reactivity';export default {name: 'HelloWorld',setup(props) {const b = reactive({x: 1})const c = readonly(b)const onClick = () => {b.x++}return () => {return (<div onClick={onClick}><p>b.x {b.x}</p><p>c.x {c.x}</p></div>)}}}
computed
在Reactivity API中,计算属性通过 computed 函数来声明。
与2.0中类似,其参数可以为一个 getter 函数也可以是一个包含 getter 和 setter 的对象。其返回值为一个ref对象,因此需要通过 .value 访问计算属性的值。
watchEffect(effect, options?)
接收一个函数以及一个选项作为参数,此函数会在组件setup时立即执行以执行依赖收集,收集到的依赖发生任何变化都会触发此函数的重新执行。
watchEffect返回一个函数,执行此函数会取消相关的副作用,此函数会在组件卸载时自动执行,也可由用户自行执行。
import {reactive} from '@vue/reactivity';import {watchEffect} from '@vue/runtime-core';export default {name: 'HelloWorld',setup(props) {const b = reactive({x: 1})const add = () => {b.x++}const stop = watchEffect(() => {console.log('changed', b.x)})return () => (<div>{b.x}<button onClick={add}>add</button><button onClick={stop}>stop</button></div>)}}
onInvalidate
effect函数接收一个参数onInvalidate,此函数会在两个时机实行:
- 每次effect重新运行时
- effect被取消时
根据文档,这个函数的应用场景主要是取消之前的依赖所带来的一系列副作用。
option
flush
这个选项主要是指定本副作用执行的时机,公有 pre , post , sync 。
pre:这个是默认值,指的是在组件更新前执行此副作用post:在组件更新后执行,一般用在需要访问DOM的场景sync:当前watcher不进入更新队列,立即执行,使用场景较少onTrack/onTrigger
这两个方法主要用于debug,前者在追踪到有依赖被收集时执行,后者在依赖被修改时触发。
watch(source, callback, options?)
对比watchEffect,watch函数有以下特点:
- 需要明确指出需要观测的变量,而watchEffect是隐式的收集依赖
- watch并不会在组件初始化时执行,只会在观测值变化时执行
-
source
对于观测值的方式,watch函数提供了三种方式:
getter函数:
() => state.user- ref值:
watch(nameRef, () => {}) ref数组:
watch([nameRef, idRef], () => {})callback
回调包含三个参数:
oldValue
- newValue
- onInvalidate
其中onInvalidate跟watchEffect作用一致
options
与watchEffect一致,不多赘述
