vue3 中的响应式处理---> Reactive

5,223 阅读2分钟

前言

reactive 类的 api 主要提供了将复杂类型的数据处理成响应式数据的能力,其实这个复杂类型是要在object array map set weakmap weakset 这五种之中(object 指的是 {}),在调用 reactive 类 api 处理数据时,有一个判断如下

if (!canObserve(target)) {
    return target
}
// 下面是 canObserver 的实现
const canObserve = (value: Target): boolean => {
  return (
    !value[ReactiveFlags.SKIP] &&  // 表示这个对象需要跳过,不能再进行 reactive 的响应式处理。比如自定义组件
    isObservableType(toRawType(value)) &&
    !Object.isFrozen(value)  // 这个对象没有被 Object.frozen() 处理过,被处理过的在非严格模式下的赋值不会报错,但是不成功
  )
}

分析如下:

  1. value[ReactiveFlags.SKIP]ReactiveFlags.SKIP 的值为 '__v_skip' 表示有此属性的值就不能转换为响应式数据,你可以自己手动给你不想转换的数据添加此属性,就会使数据必能进行响应式变换(不建议你这么做,一般自定义组件会有这个属性)。

  2. isObservableType(toRawType(value)) : 这个语句相对复杂一些,可以拆开来看

    a. toRawType(value): 这个方法是获取传入值得原始类型,比如 [] ===> Array 这个类型的获取是通过 Object.toString.call(target) 获取,然后截取的。 b.isObservableType 就是判断是否是 object array map set weakmap weakset 其中的一种,如果是就符合要求可以创建,这样子的限制也说明了 vue3 希望你是真正的想使某种数据结构变为响应式时才使用 reactive 类的 api,而不是什么数据都是进行转换。

api 记录

vue3 提出了 readonly 数据,表示数据只可读,不了修改;所以,响应式处理的 api 一般是两个版本:普通版本readonly 版本注意,这两种数据时互斥的,也就是不能互相转换,也不能同时拥有两种类型

reactive 和 readonly

一个是普通的响应式版本,一个是 只读的版本,根据需要取用。
注意: 这两个 api 会对数据进行深层次的处理,如果属性时对象,依然会处理成响应式的数据,这一点区别于下面的两个 api

reactiveShallow 和 readonlyShallow

钱响应的版本,一个是普通的响应式版本,一个是 只读的版本,根据需要取用。

小结

上面两组 api 可以理解为第一组是深拷贝,第二组是 浅拷贝

判断数据类型 api

这里的判断 api 就是其表面的语义。这里只做列举不会深入研究,会在下一节研究 vue3 使用 proxy 设置 setget 中详细分析。

  1. isReactive
  2. isReadonly
  3. isProxy
  4. toRow
  5. makRow (添加ReactiveFlags.SKIP 属性 )