返回

Vue3源码系列之触发更新的实现

前端

前言
在Vue3中,响应式系统是其核心之一,它能够自动追踪和更新数据变化,从而驱动视图的更新。在上一篇文章中,我们介绍了如何创建响应式对象,本文将继续深入剖析Vue3源码,详解触发更新的实现原理。

触发更新的时机

在Vue3中,触发更新的时机主要有两种:

  1. 数据发生变化时 :当响应式对象的数据发生变化时,Vue3会自动触发更新,从而更新视图。
  2. 调用$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中,更新视图并不是立即执行的,而是通过SchedulerflushJobs函数来实现的。

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函数负责执行更新队列中的任务,从而更新视图。