Vue.js 设计与实现
2023-01-15 10:54:18 0 举报
AI智能生成
登录查看完整内容
Vue.js 设计与实现思维导图
作者其他创作
大纲/内容
背景描述
1. 利用Object.definedProperty/Proxy劫持数据的get/set
2. 在副作用函数执行时读取数据时触发拦截font color=\"#e65100\
3. 在修改数据的属性值时触发拦截font color=\"#e65100\
基本实现
为什么使用weakMap?
key值只是字符串
为什么使用map?
去重
为什么使用set?
将bucket的数据结构从单层set数据结构改为三层结构1. 第一层使用weakMap obj为key2. 第二层使用map obj.xxx为key3. 第三层使用set将副作用函数存入
因为存储数据结构变化所以在收集/读取时候也要调整
问题1: 满足不同obj/key存在不同属性/和不同obj的副作用函数,bucket的set数据格式满足不了层级需求
添加副作用注册函数 effect,接收副作用函数它的功能有:1. 执行时将当前副作用函数赋给全局变量activeEffect2. 执行effectFn(此时会触发obj get的拦截)
修改拦截get函数1. 存入全局变量activeEffect
font color=\"#b71c1c\
完善系统
因为执行副作用函数需要前置清除依赖,所以将副作用函数套一层,1. activeEffect指向套的这一层2. 套函数增加属性deps = []3. 套函数执行副作用函数前清除依赖
触发get收集依赖1. 在读取的map层,将map推入activeEffect.deps
细节: 在拦截set触发副作用函数时,因为是Set forEach遍历,如果以前被访问过的值,删除重新推入,会继续访问,所以这里会无限循环解决方法: Set数据重新用个新Set存储再forEach执行副作用函数产生无限循环的流程:1. 修改obj.key2. 触发set3. tigger收集的副作用函数(Set forEach执行副作用函数)4. 副作用函数执行5. 清除依赖6. 触发get7. 又把副作用函数加入Set中了8. 此时Set forEach还在执行9. 访问过的值还会继续访问10. 无限循环
解决思路: 在副作用函数身上增加deps数组记录依赖的bucket的obj.key list每次拦截get时将bucket obj.key list存入deps在每次触发副作用函数时,将存储的deps遍历删除副作用函数
分支的处理
背景:在例如vue中,effect一般有组件的render方法,组件肯定是会嵌套使用的,所以effect也会出现嵌套的情况
解决思路:使用一个栈结构存储嵌套的每一个副作用函数,在执行get前将当前副作用推入,get执行后出栈,并将activeEffect指向栈顶元素,保证了每次activeEffect正确指向问题
问题1:在前面写的例子中,使用activeEffect指定当前的副作用函数,当发生effect嵌套时会导致activeEffect指向不对,导致在get时存储的副作用函数不正确
处理effect嵌套
1. trigger函数中forEach执行effectFn时判断与当前的activeEffect是否相同如果相同则不执行
解决思路:通过观察上面无限循环的流程,发现触发get的收集effectFn和set执行的effectFn是同一个函数,所以在set触发执行effectFn时判断一下是否与get时的函数是否是同一个就行
问题1:当注册副作用函数的函数中出现同一个属性又读又写的情况会出现无限循环例如 obj.foo++
处理无限循环
解决思路:梳理系统流程我们可知set后才触发副作用函数的执行,所以在副作用执行的时候我们可以用scheduler去执行副作用函数,通过set任务队列,始终保持最后一个副作用函数在队列中(相当于防抖,一个事件循环只执行最后一次)
如何实现调度执行?
实现调度执行
文章笔记链接
实现响应式系统
响应系统的作用与实现(如何实现响应系统)
Vue.js 设计与实现
0 条评论
回复 删除
下一页