Vue3源码系列之触发更新的实现
2023-10-13 13:45:21
前言
在Vue3中,响应式系统是其核心之一,它能够自动追踪和更新数据变化,从而驱动视图的更新。在上一篇文章中,我们介绍了如何创建响应式对象,本文将继续深入剖析Vue3源码,详解触发更新的实现原理。
触发更新的时机
在Vue3中,触发更新的时机主要有两种:
- 数据发生变化时 :当响应式对象的数据发生变化时,Vue3会自动触发更新,从而更新视图。
- 调用
$forceUpdate()
方法时 :当我们手动调用$forceUpdate()
方法时,Vue3也会触发更新,从而更新视图。
createSetter函数
在Vue3中,触发更新是通过createSetter
函数实现的。createSetter
函数是一个闭包函数,它返回一个函数,这个函数会在数据发生变化时调用,并触发更新。
const createSetter = (initialValue) => {
let value = initialValue;
return function setter(newValue) {
if (value !== newValue) {
value = newValue;
trigger(value);
}
};
};
createSetter
函数首先创建一个变量value
,并将initialValue
作为其初始值。然后,它返回一个函数setter
,这个函数在数据发生变化时调用。
在setter
函数中,首先检查value
是否与newValue
相等。如果不相等,则将value
更新为newValue
,并调用trigger
函数触发更新。
Scheduler与flushJobs函数
在Vue3中,更新视图并不是立即执行的,而是通过Scheduler
和flushJobs
函数来实现的。
Scheduler
是一个类,它负责管理更新队列。当触发更新时,Scheduler
会将更新任务添加到更新队列中。然后,Scheduler
会每隔一段时间调用flushJobs
函数,将更新队列中的任务执行一遍,从而更新视图。
class Scheduler {
constructor() {
this.jobs = [];
this.pending = false;
}
add(job) {
this.jobs.push(job);
if (!this.pending) {
this.pending = true;
setTimeout(() => {
this.flushJobs();
}, 0);
}
}
flushJobs() {
this.pending = false;
while (this.jobs.length) {
this.jobs.shift()();
}
}
}
Scheduler
类包含一个jobs
数组,用于存储更新任务。它还包含一个pending
属性,用于指示是否有更新任务正在等待执行。
add
方法用于将更新任务添加到更新队列中。如果pending
属性为false
,则表示没有更新任务正在等待执行,此时会调用setTimeout
函数,将flushJobs
方法延迟执行一段时间,从而避免频繁触发更新。
flushJobs
方法用于执行更新队列中的任务。它会循环遍历更新队列,并逐个执行更新任务。
总结
在Vue3中,触发更新的实现是通过createSetter
函数、Scheduler
类和flushJobs
函数来实现的。createSetter
函数负责创建响应式对象的数据更新函数,Scheduler
类负责管理更新队列,flushJobs
函数负责执行更新队列中的任务,从而更新视图。