前些天写过一篇,可是感受文章条理过于混乱,索性重写。算法
mobx
是一个简单、可扩展的状态管理库,它经过透明的函数响应式编程使得状态管理变得简单和可扩展。编程
首先打开 mobx
入口文件 src/mobx.ts
,能够发现 mobx
的共放在四个文件夹内。api
api
文件夹, 公共模块的大多数静态方法core
文件夹,mobx
大多数算法的实现types
文件夹,存放如何让对象、数组和值可观察utils
文件夹,公共方法文件向外部暴露了许多方法,好比咱们常用的 observable
、action
、computed
和 toJS
等。数组
打开 api/observable.ts
文件,找到下面代码,能够发现 observable
实际上就是 createObservable
,这里就是整个 mobx
的起点。app
export const observable: IObservableFactory &
IObservableFactories & {
enhancer: IEnhancer<any>
} = createObservable as any
复制代码
mobx
支持三种使用方法,一种为方法调用 observable()
,一种为指定方法调用,好比 observable.box()
,最后一种为装饰器 @observable
。这三个区别是方法调用和装饰器调用会针对不一样数据类型,实例化不一样的构造函数。若是是数组,会返回一个 Observable Array
。函数
observable
属性上共定义 13 种方法,其中 shallowBox
、shallowArray
、shallowMap
和 shallowObject
已经废弃。observable
每个属性对应的方法都会定义在 observableFactories
。post
Object.keys(observableFactories).forEach(name => (observable[name] = observableFactories[name]))
复制代码
若是调用这些已废弃方法,mobx
会自动帮你转换成对应的方法,并给出警告。好比:ui
shallowBox<T = any>(value?: T, name?: string): IObservableValue<T> {
if (arguments.length > 2) incorrectlyUsedAsDecorator("shallowBox")
deprecated(`observable.shallowBox`, `observable.box(value, { deep: false })`)
return observable.box(value, { name, deep: false })
}
复制代码
observableFactories
属性中 ref
、shallow
、deep
、struct
分别对应了 mobx
文件内四个 decorator
,这几个 decorator
又对应着 enhancer
。spa
observable
中每个方法内部都会首先判断当前是否以 decorator
方式调用,若是是则会报错,最后返回其对应的构造函数的实例(object
除外)。好比:code
box<T = any>(value?: T, options?: CreateObservableOptions): IObservableValue<T> {
if (arguments.length > 2) incorrectlyUsedAsDecorator("box")
const o = asCreateObservableOptions(options)
return new ObservableValue(value, getEnhancerFromOptions(o), o.name, true, o.equals)
}
复制代码
在这里,asCreateObservableOptions
方法主要根据传递进来的 options
生成实例化 ObservableValue
所需参数。getEnhancerFromOptions
会根据所生成的参数来判断应该用哪个 enhancer
。若是传递进来的 options
上有 defaultDecorator
,则使用 options.defaultDecorator.enhancer
,不然判断传递进来的 options
上 deep
是否为 false
,是则使用 referenceEnhancer
,不然 deepEnhancer
。
function getEnhancerFromOptions(options: CreateObservableOptions): IEnhancer<any> {
return options.defaultDecorator
? options.defaultDecorator.enhancer
: options.deep === false
? referenceEnhancer
: deepEnhancer
}
复制代码
createObservable
方法接收 3 个参数:v
、 arg2
和 arg3
,各对应原型对象、属性、描述符,若是不清楚为何,能够在个人另外一篇文章解读 Babel 编译后的 decorator 代码找到答案。
方法开始会判断第二个参数是否为 string
,若是是则直接返回调用 deepDecorator
的结果。
function createObservable(v: any, arg2?: any, arg3?: any) {
if (typeof arguments[1] === "string") {
return deepDecorator.apply(null, arguments)
}
...
}
复制代码
判断传入的第一个参数是否已是可观察,若是是则直接返回。若是不是,则根据不一样的数据类型,进行不一样的指定方法调用。若是都不是,则报错,并提示使用 observable.box
。
if (isObservable(v)) return v
const res = isPlainObject(v)
? observable.object(v, arg2, arg3)
: Array.isArray(v)
? observable.array(v, arg2)
: isES6Map(v)
? observable.map(v, arg2)
: isES6Set(v)
? observable.set(v, arg2)
: v
if (res !== v) return res
复制代码