响应式变量赋值
响应式变量commits首次赋值接口所返回的数据
进入触发Proxy的set拦截【在createApp的实例化的过程中,就已经将data选项响应化,可以参考之前的文章】
最终进入trigger函数
- 174行:触发副作用
- 177行:利用Reflect返回所赋值的内容,具体可查看(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/set)
trigger
进入trigger内部
- target实际上是选项式中的data
- targetMap是从一开始注册响应化就收集的响应映射表
执行trigger
startBatch()
和endBatch()
:
startBatch()
用于开启一个批量更新的阶段。在这个阶段中,响应式数据的变化不会立即触发依赖的更新,而是会被收集起来,等到endBatch()
被调用后再统一进行处理。这样做的好处是可以避免在短时间内频繁地触发更新,从而提高性能。例如,在一个循环中多次修改响应式数据时,可以使用批量更新来减少不必要的重复更新操作。
- __DEV__:开发环境下传入数据信息便于调试
- dep.trigger():触发依赖更新
trigger下又执行notify
封装在
notify
通过遍历订阅链表(subsHead),执行订阅事件,也就是“副作用”,简而言之的理解就是通知订阅者更新
link.sub.notify()
- 作用:通知每个订阅者执行其副作用。
- 解释:每个订阅者都有一个
notify
方法,调用它会触发该订阅者的副作用执行。因为是从尾到头通知,所以确保了所有的依赖在批处理内按顺序执行。
当trigger执行完,同时Proxy的set流程也结束。
下一步执行到PublicInstanceProxyHandlers
PublicInstanceProxyHandlers
这个是组件实例行为的封装,上述响应式变量赋值完成,然后进入当前的组件实例属性设置
set
方法用于拦截和处理对组件实例属性的修改操作
主线程工作结束
微任务flushJobs
执行异步的flushJobs
flushJobs
是一个用于刷新调度队列的函数,它会执行所有被调度的任务(如组件更新、计算属性的重新计算等)
- 调度器调度任务:
- Vue 3 的调度器会负责管理这个调度队列。调度器会尝试合并重复的任务,确保每个任务只执行一次,并且按照一定的顺序(如父组件先于子组件,先更新计算属性再更新渲染函数)进行调度。
queueFlush
触发:- 当有新的任务被添加到调度队列时,调度器会调用
queueFlush
函数,将刷新任务安排到下一个微任务(microtask)中执行。 - 这通常是通过
Promise.resolve().then(flushJobs)
来实现的。Promise.resolve().then(...)
会创建一个新的微任务,在当前同步任务结束后立即执行。这样做的好处是保证所有的同步任务(如多个响应式数据的set
操作)都完成之后,再一次性执行批量更新操作。 - 执行
flushJobs
: - 一旦所有的同步操作完成,事件循环进入到微任务队列,
flushJobs
函数被调用。flushJobs
会遍历调度队列,并依次执行每个调度任务(如重新渲染组件、重新计算计算属性等)。 - 在这个阶段,所有的
effect
被重新执行,更新视图、计算新的值等等。
评论区