vue3.0 reactive 理解
reactive 简记
1. 需要注意的是,只有 typeof val=== ‘object’ 的数据才能使用这个api 转换为响应式数据(如果你违反了这个规则,开发模式下回给你友好亲切的提示)
2. 如果你传入的对象本来是 readonly() 的只读数据,但是你将其传入 reactive 时,会直接将这个数据返回。因为转换不了。
3. 如果你传入的数据 reactive 的响应式数据,则会直接返回。
他的判断如下:
这里主需要记住一点,isReadonly 和 target[ReactiveFlges.IS_REACTIVE] 一般情况下是互斥的,也就是只要你的数据时经过 readonly 或者 reactive 转换的,一定会给你返回你传入的原值。所以你明白了吗,readonly 和 reactive 是互斥的数据结构,不能同时使一个数据具有两种响应式结构,这里说明人家考虑的很全面,完美。
if(target[ReactiveFlges.RAW] && !(isReadonly && target[ReactiveFlges.IS_REACTIVE])) {
return target
}
4. 当你传递了一个响应式数据 reactive,如果本身是 reactive 的数据结构,但是你想得到一个 readonly 的结构,对不起,不会给你。
如果一个对象的 ReactiveFlags.RAW === “__v_raw”存在,就说明已经进行过了响应式处理,接下来的处理是 !(isReadonly && target[ReactiveFlags.IS_REACTIVE]) 前面说过当这个数据时响应式数据时,这俩条件是互斥的,所以这里就直接返回了传入数据,不会再做一层包装。
5. 你的数据不止要是 typeof === ‘object’,你还必须的是以下的几种数据结构,不然任性不给你转
Object, Array, Map, Set, WeakMap, WeakSet 3.0 给出的数据结构转换的白名单,这点需要注意,不然得不到响应数据。
这个白名单的另外两个判断条件是 对象不能被 makRaw 处理过,判断是否具有ReactiveFlags.SKIP === "__v_skip"属性
还有不能经过 Object.frozen() 处理
6. 如果你成功地通过了前面这几道检测,那么恭喜你,你可以如愿以偿的获得你期望中的新的响应式数据
7。 需要遵守上述规则的 api 有
reactive
shallowReactive
readonly
shallowReadonly
上面的四个 api 他们在内部出了 proxy 的 handler 不同,都是调用 createReactiveObject 进行数据转换的
8。检测方法
对应的检测方法有
isReactive 方法
isReadonly 方法
isProxy 方法
9. 将数据转换回去
makRaw 显示的标记某个对象永远不会成为响应式对象,主要是为对象增加了 ReactiveFlags.SKIP === "__v_skip"属性
toRaw 方法将会获得你传入的原始数据,它主要是通过 ReactiveFlags.RAW === "__v_raw" 属性,这个属性在 proxy 的 handler 的get 函数中会直接返回传入的原始对象,但是其实会多一个 __v_reactive 属性(也有可能是__v_readonly),记录响应式对象
__v_reactive 和 _v_readonly 这两个属性只能有一个存在在源对象上,他们是在 proxy 处理完对象后,使用
key 就是 __v_reactive 和 _v_readonly 其中之一,主要看你的响应式数据时从哪个响应式 api 中获得的
Object.defineProperty(obj, key, { // vue3.0 并没有忘记他
configurable: true,
enumerable: false, //不可枚举
value // proxy 后的响应式对象
})