前言
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() 处理过,被处理过的在非严格模式下的赋值不会报错,但是不成功
)
}
分析如下:
-
value[ReactiveFlags.SKIP]:ReactiveFlags.SKIP的值为'__v_skip'表示有此属性的值就不能转换为响应式数据,你可以自己手动给你不想转换的数据添加此属性,就会使数据必能进行响应式变换(不建议你这么做,一般自定义组件会有这个属性)。 -
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 设置 set 和 get 中详细分析。
- isReactive
- isReadonly
- isProxy
- toRow
- makRow (添加ReactiveFlags.SKIP 属性 )