前言
let target = observable(obj)
在Mobx中Atom用来监测数据被观察和修改,在设置target的属性描述符的时候,对应每一个key都会创建一个一个Atom的子类ObservableValue实例。
ObservableValue
如果obserable(obj)的返回值target是"明",而obj是"暗",那么ObservableValue实例则是"明"通往"暗"的单向桥梁。对target相应key的getter和setter都调用了这个实例的相应方法。
- value_
这个属性保存了obj对象的对应的key的
descriptor.value - get:
当访问target的属性的时候,会调用这个方法。返回的就是原obj对象对应key的相应value
reportObserved,
public get(): T {
this.reportObserved()
return this.dehanceValue(this.value_)
}
get的调用说明该key被依赖,其会调用reportObserved处理依赖。
- reportObserved
这个方法继承自父类
Atom,该函数中最有价值的事情是确定依赖关系。
export function reportObserved(observable: IObservable): boolean {
...
const derivation = globalState.trackingDerivation
if (derivation !== null) {
if (derivation.runId_ !== observable.lastAccessedBy_) {
observable.lastAccessedBy_ = derivation.runId_
derivation.newObserving_![derivation.unboundDepsCount_++] = observable
if (!observable.isBeingObserved_ && globalState.trackingContext) {
observable.isBeingObserved_ = true
observable.onBO()
}
}
return true
} else if (observable.observers_.size === 0 && globalState.inBatch > 0) {
queueForUnobservation(observable)
}
return false
}
globalState.trackingDerivation是一个IDerivation类型的数据,或者称之为"派生",它有一个大名鼎鼎的实现类,叫Reaction。可以简单理解:derivation是observable数据的观察者。
当这段代码运行的时候就会创建出一个reaction,并挂到globalState.trackingDerivation上,这个过程在解析autorun源码的时候再具体分析。
auturun(()=>{...})
总之,这里通过derivation.newObserving_![derivation.unboundDepsCount_++] = observable,确定了derivation对这个ObservableValue实例有依赖。
- set和setNewValue
当对target设置/修改值的时候会调用
set或setNewValue,set内部也调用了setNewValue.
public set(newValue: T) {
const oldValue = this.value_
newValue = this.prepareNewValue_(newValue) as any
...
if (newValue !== globalState.UNCHANGED) {
this.setNewValue_(newValue)
}
}
setNewValue_(newValue: T) {
const oldValue = this.value_
this.value_ = newValue
this.reportChanged()
...
}
setNewValue触发时说明value变更,需要通知依赖进行相应的处理,这里调用的是reportChanged。
- reportChanged
这个方法也继承自父类
Atom
public reportChanged() {
startBatch()
propagateChanged(this)
endBatch()
}
propagateChanged从ObservableValue实例observable中找到对它有依赖的所有derivation,并调用onBecomeStale_,这个方法在Reaction中定义,它在经过了一系列复杂的调用后,能够使得依赖的函数再次运行。
export function propagateChanged(observable: IObservable) {
// invariantLOS(observable, "changed start");
if (observable.lowestObserverState_ === IDerivationState_.STALE_) return
observable.lowestObserverState_ = IDerivationState_.STALE_
// Ideally we use for..of here, but the downcompiled version is really slow...
observable.observers_.forEach(d => {
if (d.dependenciesState_ === IDerivationState_.UP_TO_DATE_) {
if (__DEV__ && d.isTracing_ !== TraceMode.NONE) {
logTraceInfo(d, observable)
}
d.onBecomeStale_()
}
d.dependenciesState_ = IDerivationState_.STALE_
})
// invariantLOS(observable, "changed end");
}
未完待续
Mobx中“观察”部分的代码到这里就基本结束了,但是遗留了两个问题:globalState.trackingDerivation是何时确定的以及observable.observers_又是如何收集的。
下一节将开始Mobx“反应”部分的源码解析,回答这两个问题