在vue 3中实现响应式的主要是reactive 和ref 函数。那我们今天就来实现一个reactive。
一、创建代理对象
vue3中的响应式的底层原理已经换成了proxy ,则reactive 函数返回的是一个proxy代理对象,我们先创建一个reactive.js文件

上面呢,我们简单实现了一个reactive函数,接受一个源对象,然后代理了源对象的get和set行为后返回一个代理对象。写个html,引入js测试一下

成功返回代理对象,并触发get和set行为

二、实现effect
第一步我们已经实现了代理对象,我们目前只能去监听代理对象的set和get操作,这样是远远不够的。如下

我们将age显示在页面上,两秒后去修改age属性,如何实现页面同步更新呢?
接下来引入一个新的函数 effect
effect 翻译过来就是作用的意思,那我们期望effect实现什么作用呢?当然是当代理对象更新属性触发set行为时,自动去执行某些操作。
好了,我们了一个目标,那就去实现它吧。新建一个effect.js文件,根据目标effect函数应该接受一个函数参数。
此时的参数就是我们去修改dom节点的函数,并且这个函数要被执行。我们很容易就实现以下代码

此时,接收fn并执行,会触发函数中的代理对象的get行为。那我们如何将fn与代理对象的属性进行绑定呢?这就要引出另一个概念: 依赖收集
三、实现依赖收集
在哪一步进行依赖收集呢?从第二步就可以知道,我们在代理对象触发get行为的时候进行依赖收集。
首先,在触发get行为时,我们可以获取到源对象target,对象属性key。我们需要设计一下数据结构来存储对应的关系。

接下来就去实现依赖收集track函数

这里引入了一个activateEffect的变量,用于存储当前effect执行的函数

然后在代理对象的get行为触发的时候执行track就行了,如下

四、依赖触发
前面我们已经实习了依赖收集,下面到了依赖触发的阶段了。当代理对象触发set时,我们应该触发对应的函数。我们只需要根据原函数和字段来层层获取对应依赖就可以了,代码如下

在set函数触发的时候进行依赖触发

五、打包构建
之前都是直接在html中进行引入,这样不是很好,我们需引入一个专门打包js的工具,那就是rollup。我们只需要安装npm i rollup,然后在根目录创建rollup.config.js 文件,执行输入文件和输出文件即可。 配置文件内容如下:

其中format我们设置成iife,就是立即执行函数。然后我们指定一个打包文件入口index.js,然后在index.js中引入我们需要的函数。

然后在package.json 中配置打包脚本

然后只管build就行。再build生成的bundle文件引入html文件中。如下

然后使用插件live server打开html文件,发现两秒后网页上的内容发生了变化,则一个简单的reactive就实现了。
六、总结
为了实现reactive功能,我们引入了很多概念。首先就是返回Proxy对象,在返回代理的对象的过程中,我们监听了代理对象的get和set函数,在触发get时进行依赖收集,在触发set时进行依赖触发。同时,我们还引入了effect函数,自动执行传入函数,设计数据weakmap数据结构存储target、key、dep之间的关系。由于实现的比较简单,没有像Vue中的实现很多的类,如Dep,reactiveEffect类,大家如果感兴趣可以看一下我的GitHub,地址如下github.com/Wkb2317/my-... 也是跟着sunday老师的课程进行敲的代码,欢迎start,非常感谢。