返回

Mobx 源码解析(二):深入解析 ComputedValue

前端

前言

在上一章中,我们对 Mobx 的基本概念和整体架构进行了介绍。我们了解到,Mobx 的核心思想是通过观察者模式来实现响应式更新。在这一章中,我们将深入分析 Mobx 中 ComputedValue 类的源码实现,了解其内部运作机制以及如何实现响应式更新。我们将从 ComputedValue 类的定义开始,然后逐步探究其关键方法和属性,揭示其作为 Mobx 响应式系统基石的作用。

ComputedValue 类的定义

ComputedValue 类是 Mobx 中一个重要的类,它是响应式计算的基础。该类实现了 IObservable, IComputedValue, IDerivation 三个接口,其中 IObservable 接口定义了可观察对象的公共方法和属性,IComputedValue 接口定义了计算值特有的方法和属性,IDerivation 接口定义了派生对象(如计算值和反应式跟踪器)的公共方法和属性。

export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDerivation {
  ...
}

ComputedValue 类的关键方法和属性

构造函数

ComputedValue 类的构造函数接收一个计算函数作为参数,该函数用于计算 ComputedValue 的值。在构造函数中,会创建一个新的派生对象(即 ComputedValue 实例),并将其添加到 Mobx 的派生对象列表中。同时,还会创建一个反应式跟踪器,用于跟踪 ComputedValue 所依赖的可观察对象的变化。

constructor(options: IComputedValueOptions<T>) {
  ...
  this._derivation = new ComputedValueDerivation(this, options.get, options.set, options.name);
  ...
}

get 方法

get 方法是 ComputedValue 类的一个重要方法,它用于获取 ComputedValue 的值。当调用 get 方法时,会首先检查 ComputedValue 是否已经计算过其值。如果已经计算过,则直接返回计算结果。如果尚未计算,则会调用计算函数计算 ComputedValue 的值,并将计算结果缓存起来。

get(): T {
  ...
  if (this.isComputing !== true) {
    this.trackAndCompute();
  }
  if (globalState.strict && !this.isComputing && (this.dependenciesState === 1 || this.dependenciesState === 3)) {
    console.warn(`[MobX] Computed value ` + this.name + ` is being read outside a reactive context`);
  }
  ...
}

set 方法

set 方法是 ComputedValue 类的一个可选方法,它用于设置 ComputedValue 的值。当调用 set 方法时,会首先检查 ComputedValue 是否允许被设置。如果允许,则会调用计算函数计算 ComputedValue 的新值,并将新值缓存起来。同时,还会通知所有依赖于该 ComputedValue 的可观察对象更新其值。

set(value: T): void {
  ...
  if (this.setter !== undefined) {
    this.setter.call(this.context, value);
  } else if (globalState.strict) {
    console.warn(`[MobX] Computed value ` + this.name + ` is trying to update itself. ` + `It will be readonly after the next turn.`);
  }
  ...
}

autorun 方法

autorun 方法是 ComputedValue 类的一个静态方法,它用于创建一个反应式跟踪器。反应式跟踪器会跟踪 ComputedValue 所依赖的可观察对象的变化,并在这些可观察对象变化时自动重新计算 ComputedValue 的值。

static autorun(f: IAutorunOptions | IFn0<IDisposer>): IDisposable {
  const reaction = new Reaction(undefined, f, undefined, false);
  reaction.runReaction();
  return reaction.getDisposer();
}

ComputedValue 类作为 Mobx 响应式系统基石的作用

ComputedValue 类是 Mobx 响应式系统的一个基石。它允许开发者定义计算值,这些计算值可以依赖于其他可观察对象。当这些可观察对象发生变化时,ComputedValue 会自动重新计算其值,并通知所有依赖于它的可观察对象更新其值。这种响应式更新机制使得 Mobx 能够轻松地构建出复杂的、响应式的应用程序。

总结

在这一章中,我们深入分析了 ComputedValue 类的源码实现,了解了其内部运作机制以及如何实现响应式更新。我们从 ComputedValue 类的定义开始,然后逐步探究其关键方法和属性,揭示其作为 Mobx 响应式系统基石的作用。通过对 ComputedValue 类的深入理解,我们对 Mobx 的响应式编程模型有了更深入的认识。