编写响应式模块reactivity模块-详细步骤

169 阅读2分钟

我们先看一下官方的reactivity模块

image.png image.png

reactivity模块中最重要的两个api,effect和reactive

  • effect代表的是副作用函数,如果此函数依赖的数据发生了变化,会重新执行 
  • reactive将数据变成响应式

用法

image.png

衍生api-shallowReactive,readonly,shallowReadonly

  • shallowReactive只代理第一层,其它层对象不会去用proxy代理
  • readonly仅读,不管多少层都不能改
  • shallowReadonly,只是第一层不能改

现在我们自己来实现,引入自己包

image.png

在src下创建effect.ts文件和reactive.ts文件

image.png

image.png

在src下的index.ts中导出这两个方法

image.png

我们先来写reactive方法

先判断传入的参数是否是对象,reactive只能代理对象,如果参数不是对象直接return

image.png

使用proxy进行代理

image.png

用Reflect的原因

image.png

  • 用Reflect的原因就是把Reflect会把取的值里面的this改成代理对象
  • 上面的例子中如果name改变了,我们就不重新执行了么?所以我们不直接取,而是用Reflect去取

问题1:如果一个对象被代理多次

image.png

  • 很明显不等于,放了两次,被代理了两次
  • 如果一个对象被代理多次会影响性能

我们就可以考虑进行缓存,使用WeakMap缓存起来

  • 我们用WeakMap的原因是不会造成内存泄露
  • 它的key只能是对象

image.png image.png

问题2:如果连续代理

image.png

加标识解决

image.png

然后判断

image.png

get中加这样一个标识

image.png

  • 第一次普通对象代理,我们会通过new Proxy代理一次
  • 下一次你传递的是proxy,我们可以看一下他有没有代理过,如果访问这个proxy有get方法的时候就说明访问过了
  • 简而言之,我们在代理前,先去访问这个对象,如果它被代理过,那么身上就有get方法,我们就能得到true的结果,那么就可以判断它被proxy代理过,我们就直接把该对象返回出去
  • 其实我们也没有加标识,我们只是为了命中get,来判断该对象是否被代理过

抽离proxy中的处理逻辑

image.png

image.png

  • 这样做的好处就是我们就不用再关注reactive文件了,只关注抽离后的文件里的逻辑