-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
手动实现Vue3 & 原理解析:setup环境 & reactive函数 & effect函数(一) #1235
Comments
手动实现Vue3 & 原理解析:setup环境 & reactive函数 & effect函数(一) by 三分钟学前端回复交流,加入前端编程面试算法每日一题群 前言本篇解析参阅 vue3源码、崔大的mini-vue、霍春阳大佬的《Vuejs设计与实现》尽可能记录我的Vue3源码阅读学习过程。我会结合自己的思考,提出问题,找到答案,附在每一篇的底部。希望大家能在我的文章中也能一起学习,一起进步,有 get 到东西的可以给作者一个小小的赞作为鼓励吗?谢谢大家! 手写简易vue3 setup环境 && reactive函数 && effect函数setup环境
当前项目主要采用 说明: 所以需要安装如下的依赖包:
附带安装指令:
重点介绍以下配置:
创建
创建
至此,初始开发环境 setup 完毕 reactive 函数众所周知,vue3 采用 Proxy 来代理对象,通过劫持方法来实现响应式
reactive 函数的初步实现初步实现:
相关问题:Proxy是什么?Reflect是什么?为什么要用Reflect?[1] 接下来,我们需要实现 在 依赖收集 & 触发依赖依赖收集我们将它封装为一个 触发依赖我们将它封装为一个 这里首先要依赖一个 副作用函数产生的 activeEffect[2] 欢迎回来,这时候我们已经知道了 activeEffect 的由来 依赖收集: 我们想要收集依赖,得知道是哪个对象(target) 的哪个 key 吧?还得知道对应这个 key 有哪些依赖 这里我们采用的方法是:
类似这样的结构: WeakMap ├─ Map Obj1 │ ├─ Set Obj1.key1 │ │ ├─ ReactiveEffectA │ │ └─ ReactiveEffectB │ ├─ Set Obj1.key2 │ └─ Set Obj1.key3 ├─ Map Obj2 └─ Map Obj3 依赖执行: 依赖的执行就比较简单了,就是
实现 readonly我们现在有一个需求, 根据需求,我们不难得到修改方案:
那么我们可以新增 readonly 函数,返回一个 和 reactive 不一样的代理对象:
那显然我们发现这个代码和我们的 reactive 极其相似,我们 语义化 new Proxy
实现 createSetter 和 createGetter 方法并分别导出 handlers
那么封装完成后,我们去生成响应式的代理对象/只读的代理对象就可以调用以下方法:
是不是清爽了非常多呢!! 实现 isReactive / isReadonly 方法我们现在还需要两个方法 那么我们需要增加 ReactiveFlag元组 、 isReactive方法 、 isReadonly方法,修改 createGetter方法:
这里并不复杂,就是通过 创建 get 时的 isReadonly 参数来返回响应的值即可 实现 shallowReactive / shallowReadonly 函数我们还希望面对一个嵌套对象,我们不想他内部的属性对象也变成一个 响应式/只读 的代理对象,在 vue2 里我们可以利用 那在 vue3 我们要怎么实现呢?其实基于上边的代码,我们只需要停止对内部对象做递归即可。 那我们需要创建对 createGetter 做修改,并利用
接着我们需要创建 shallowReactive 、 shallowReadonly 方法,使用这两个handler:
ok! 大功告成,这里的实现也并不复杂。让我们接着往下看! effect 函数effect 函数我们也称作 顾名思义,就是当 effect 函数 初步实现当我们调用 effect 函数的时候 需要 内部生成一个 从这个命名上我们也能知道
关键点就是我们的这个 这里我们可以回到 reactive 的依赖收集以及触发依赖[3] effect 函数优化 ———— 调用 effect 的时候应该返回当前的执行函数我们希望 附 jest 测试用例:
因此我们需要对我们的 effect 函数做出以下修改:
这样子之后我们调用 effect 之后就能拿到这个 runner 对应的其实就是 ReactiveEffect 实例 的 run 方法 effect 函数优化 ———— scheduler函数选项我们希望 effect 可以传入 一个 scheduler函数选项 当传入了 scheduler 的时候,
附上相应的 jest 测试用例:
为此,我们需要对我们的 effect函数 、 ReactiveEffect类 、trigger函数 做出修改:
ok,这样我们就能实现我们的要求了,重复一遍!!
effect 函数优化 ———— stop 方法 以及 onStop hooks我们又有新的需求了!!! 我们希望有一个 stop 方法,当我们调用 stop方法时 我们还希望每次 先看测试用例:
为此,我们先整理下我们要做的事:
注意前方高能!!!!! 修改 effect函数 、 ReactiveEffect类 、track函数,新增 stop方法 、 cleanupEffect方法 、 isTracking方法 ,新增 shouldTrack 全局变量 如下:
OK。我们可以看到这一次我们是加了很多东西,不要怕,我们来重点解释一下。 ReactiveEffect类中的
问题:Proxy是什么?Reflect是什么?为什么要用Reflect?
代理:对一个对象基本语义代理,
Reflect 的功能: 提供了一个访问对象属性的默认行为,实际上以下的行为是等价的:
那么新的问题来了: 实际上 Reflect 的函数可以接收 比如:
当然 Reflect 还有其他的功能特性:JS 标注内置对象--Reflect[4] 我们这里暂时只关心这个,因为它与响应式数据的实现密切相关。 关于本文 作者:啊Ben学前端https://juejin.cn/post/7084244897753989133 最后120 套模版 |
https://mp.weixin.qq.com/s?__biz=Mzg2NjUxOTM2Mg==&mid=2247494682&idx=1&sn=968096ef30a7f04b684a5ff182bc4f5e
The text was updated successfully, but these errors were encountered: