我们先看一下官方的reactivity模块
reactivity模块中最重要的两个api,effect和reactive
- effect代表的是副作用函数,如果此函数依赖的数据发生了变化,会重新执行
- reactive将数据变成响应式
用法
衍生api-shallowReactive,readonly,shallowReadonly
- shallowReactive只代理第一层,其它层对象不会去用proxy代理
- readonly仅读,不管多少层都不能改
- shallowReadonly,只是第一层不能改
现在我们自己来实现,引入自己包
在src下创建effect.ts文件和reactive.ts文件
在src下的index.ts中导出这两个方法
我们先来写reactive方法
先判断传入的参数是否是对象,reactive只能代理对象,如果参数不是对象直接return
使用proxy进行代理
用Reflect的原因
- 用Reflect的原因就是把Reflect会把取的值里面的this改成代理对象
- 上面的例子中如果name改变了,我们就不重新执行了么?所以我们不直接取,而是用Reflect去取
问题1:如果一个对象被代理多次
- 很明显不等于,放了两次,被代理了两次
- 如果一个对象被代理多次会影响性能
我们就可以考虑进行缓存,使用WeakMap缓存起来
- 我们用WeakMap的原因是不会造成内存泄露
- 它的key只能是对象
问题2:如果连续代理
加标识解决
然后判断
get中加这样一个标识
- 第一次普通对象代理,我们会通过new Proxy代理一次
- 下一次你传递的是proxy,我们可以看一下他有没有代理过,如果访问这个proxy有get方法的时候就说明访问过了
- 简而言之,我们在代理前,先去访问这个对象,如果它被代理过,那么身上就有get方法,我们就能得到true的结果,那么就可以判断它被proxy代理过,我们就直接把该对象返回出去
- 其实我们也没有加标识,我们只是为了命中get,来判断该对象是否被代理过
抽离proxy中的处理逻辑
- 这样做的好处就是我们就不用再关注reactive文件了,只关注抽离后的文件里的逻辑