简介
响应式模块主要是将对象经过Proxy代理,同时根据shallow,readonly不同的参数,组合成四种响应式类型。由于经过代理的过程基本一样,只是handler处理方式存在差异。故采用柯里化的思想,基于createReactiveObject生成四种类型响应式方法。
主要方法分析
createReactiveObject
- 参数说明
- target: 要被代理的对象
- isReadonly: 是否只读
- baseHandlers: 具体处理方法对象
- collectionHandlers: 集合类型处理方法对象
- proxyMap: 全局代理存储对应,避免重复代理
- 处理逻辑
- 只对
Object处理,非对象直接返回原对象 - 已经是响应式了,直接返回
- 查找
proxyMap是否已经存在,若是则表示代理过,直接取已经代理过的对象 - 对象中也要再判断一次类型,只有是
Object,Array,Map/WeakMap,Set/WeakSet这几种数据类型才做代理 - 调用
Proxy返回代理对象,同时将代理过之后的对象存入缓存中
集合类型则调集合对应的
handler - 只对
全局定义变量
- 响应式类型
- skip
- reactive
- readonly
- shallow
4种对应的WeakMap,存储经过Proxy代理之后的对象,避免重复代理
WeakMap对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。
正由于这样的弱引用,WeakMap 的 key 是不可枚举的(没有方法能给出所有的 key)。如果key 是可枚举的话,其列表将会受垃圾回收机制的影响,从而得到不确定的结果。因此,如果你想要这种类型对象的 key 值的列表,你应该使用 Map。
- 判断Reactive对象属于那种具体类型
- isReadonly 根据ReactiveFlags.IS_READONLY变量判断
- isReactive 如果是isReadonly,就判断RAW类型是否Reactive
- isShallow 根据ReactiveFlags.IS_SHALLOW变量判断
- isProxy 是Reactive或者Readonly
- toRaw
先判断target是否存在ReactiveFlags.RAW,存在则对raw对象继续进行toRaw调用,否则返回本身 - markRaw
标记Raw类型,即设置对应对象的ReactiveFlags.SKIP设置为true - toReactive
是对象则调用reactive方法,否则返回自身 - toReadonly
handler
baseHandlers
通过createGetter,createSetter两个方法传入不同的参数(isReadonly和shallow)组合成对应的handler
createGetter
不同的key处理策略不一样
- 先处理当访问的
key是ReactiveFlags的情况,直接返回target- 访问
RAW属性时,先判断当前receiver与对应的Map缓存中取出代理对象是否一致
- 访问
- target是数组,且不是只读,访问的
key在arrayInstrumentations中时createArrayInstrumentations
- 需要遍历数组所有元素的方法['includes', 'indexOf', 'lastIndexOf']
- 会改变元素length属性的方法['push', 'pop', 'shift', 'unshift', 'splice']
通过
Refelct.get获取原来对象的值之后,处理返回结果res
key是Symbol时,如果是内建属性或者访问的是不收集依赖的属性(__proto__,__v_isRef,__isVue)时,直接返回获取的值- 非只读时,收集依赖
- shallow为真时,表示只处理第一层,直接返回
- 如果是Ref类型,需要unwrap,直接返回值,但是针对数组或者访问的是key是整型,则不做unwrap处理
- 如果返回的是一个Object,则需要再次调用
reactive方法,继续递归处理访问时,才收集依赖
createSetter
先获取旧值oldValue,如果旧值是只读的,并且是一个Ref且新值不是Ref,则返回false
- 要设置的key是否是新增,数组下标,且小于数组长度,或者是在对象已有属性中,则都不是新增
- trigger触发