上文我们推测Mobx的基本原理,并模拟实现了Mobx的两个核心api,本文将进入源码,看看observable是如何实现的。
不简单的observable
observable并不仅仅是一个方法,应该将它看成是一个对象。
Mobx对observable的定义在packages/mobx/src/api/observable.ts中:
function createObservable(v: any, arg2?: any, arg3?: any) {}
Object.assign(createObservable, observableDecoratorAnnotation)
export var observable: IObservableFactory = assign(createObservable, observableFactories)
这么一顿操作后,observable除了可以作为一个方法调用,还具有这些能力:
const observable = function(){...}
Object.assign(observable,{
box(){},
array() {},
map() {},
set() {},
object() {},
ref: ...,
shallow: ...,
deep: ...,
struct: ...,
annotationType_: ...,
options_: ...,
make_(){},
extend_(){}
})
这四个属性来自于createObservableAnnotation方法创建出的对象
{
annotationType_: name,
options_: options,
make_,
extend_
}
其他的属性来自于observableFactories对象。
observable的函数体是这样的:
function createObservable(v: any, arg2?: any, arg3?: any) {
...
if (isObservable(v)) return v
// plain object
if (isPlainObject(v)) return observable.object(v, arg2, arg3)
// Array
if (Array.isArray(v)) return observable.array(v, arg2)
...
return observable.box(v, arg2)
}
observable会根据参数类型,再调用相对应的方法:
observable.object
假设我们调用的形式时observable(obj),obj是一个plain object,它实际调用的是observableFactories.object,它的返回值如下:
extendObservable(
globalState.useProxies === false || options?.proxy === false
? asObservableObject({}, options)
: asDynamicObservableObject({}, options),
props,
decorators
)
可以看到返回的值是从一个空对象{}创建的。
根据是否使用Proxy,分别调用asDynamicObservableObject和asObservableObject来对这个空对象做处理。
asObservableObject和extendObservable
asObservableObject对这个{}对象增加了一个$mobx属性,这是一个ObservableObjectAdministration实例。后文将称这个对象为target
export function asObservableObject(
target: any,
options?: CreateObservableOptions
): IIsObservableObject {
if (hasProp(target, $mobx)) {
return target
}
const adm = new ObservableObjectAdministration(
target,
new Map(),
"ObservableObject",
getAnnotationFromOptions(options)
)
addHiddenProp(target, $mobx, adm)
return target
}
extendObservable则将这个target与我们传入的obj对象进行了关联。
export function extendObservable<A extends Object, B extends Object>(
target: A,
properties: B,
annotations?: AnnotationsMap<B, never>,
options?: CreateObservableOptions
): A & B {
const descriptors = getOwnPropertyDescriptors(properties)
const adm: ObservableObjectAdministration = asObservableObject(target, options)[$mobx]
startBatch()
try {
ownKeys(descriptors).forEach(key => {
adm.extend_( key, descriptor[key as any],true)
})
} finally {
endBatch()
}
return target as any
}
extendObservable中会将我们传入的obj对象的key和对应的descriptor,通过ObservableObjectAdministration实例adm的extend_方法,加到target上。
未完待续
到这里observable方法的运行就已经全部梳理完了,但我们并没有窥见Mobx的丝毫底层原理。而且我们还遇到了一个陌生的对象ObservableObjectAdministration。“可观察对象管理器”,从命名上就可以看出,这是一个在Mobx中非常关键的class,而正是它将会带我们拨开Mobx神秘的面纱。
且听下回分解。