在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自动展开的情况有两个:

  1. 如果使用vue模板,则ref的值可以不需要使用 .value进行访问。
  2. 如果ref是作为 reactive 对象的属性值,那么通过相关属性也无需 .value 进行访问(注意这对其余reactive引用类型不适用,如Array,Map等等)**

    readonly

    readonly可以接受一个reactive或者ref作为参数,返回一个无法修改的reactive或ref。

这相当于给原来的reactive或ref套了一层readonly的壳,通过这个返回值是无法进行修改操作,但readonly的值仍然与其参数进行同步。下面代码中 b.x 的变化会同时反映到 c.x 身上:

  1. import {reactive, readonly} from '@vue/reactivity';
  2. export default {
  3. name: 'HelloWorld',
  4. setup(props) {
  5. const b = reactive({x: 1})
  6. const c = readonly(b)
  7. const onClick = () => {
  8. b.x++
  9. }
  10. return () => {
  11. return (
  12. <div onClick={onClick}>
  13. <p>b.x {b.x}</p>
  14. <p>c.x {c.x}</p>
  15. </div>
  16. )
  17. }
  18. }
  19. }

computed

在Reactivity API中,计算属性通过 computed 函数来声明。

与2.0中类似,其参数可以为一个 getter 函数也可以是一个包含 gettersetter 的对象。其返回值为一个ref对象,因此需要通过 .value 访问计算属性的值。

watchEffect(effect, options?)

接收一个函数以及一个选项作为参数,此函数会在组件setup时立即执行以执行依赖收集,收集到的依赖发生任何变化都会触发此函数的重新执行。

watchEffect返回一个函数,执行此函数会取消相关的副作用,此函数会在组件卸载时自动执行,也可由用户自行执行。

  1. import {reactive} from '@vue/reactivity';
  2. import {watchEffect} from '@vue/runtime-core';
  3. export default {
  4. name: 'HelloWorld',
  5. setup(props) {
  6. const b = reactive({x: 1})
  7. const add = () => {
  8. b.x++
  9. }
  10. const stop = watchEffect(() => {
  11. console.log('changed', b.x)
  12. })
  13. return () => (
  14. <div>
  15. {b.x}
  16. <button onClick={add}>add</button>
  17. <button onClick={stop}>stop</button>
  18. </div>
  19. )
  20. }
  21. }

onInvalidate

effect函数接收一个参数onInvalidate,此函数会在两个时机实行:

  1. 每次effect重新运行时
  2. effect被取消时

根据文档,这个函数的应用场景主要是取消之前的依赖所带来的一系列副作用。

option

flush

这个选项主要是指定本副作用执行的时机,公有 pre , post , sync

  • pre :这个是默认值,指的是在组件更新前执行此副作用
  • post :在组件更新后执行,一般用在需要访问DOM的场景
  • sync :当前watcher不进入更新队列,立即执行,使用场景较少

    onTrack/onTrigger

    这两个方法主要用于debug,前者在追踪到有依赖被收集时执行,后者在依赖被修改时触发。

这两个函数是针对每个单独的依赖而执行。

watch(source, callback, options?)

对比watchEffect,watch函数有以下特点:

  1. 需要明确指出需要观测的变量,而watchEffect是隐式的收集依赖
  2. watch并不会在组件初始化时执行,只会在观测值变化时执行
  3. 可以同时获取变量的旧值与新值

    source

    对于观测值的方式,watch函数提供了三种方式:

  4. getter函数: () => state.user

  5. ref值: watch(nameRef, () => {})
  6. ref数组: watch([nameRef, idRef], () => {})

    callback

    回调包含三个参数:

  7. oldValue

  8. newValue
  9. onInvalidate

其中onInvalidate跟watchEffect作用一致

options

与watchEffect一致,不多赘述