Mobx 源码分析 - 第一阶段汇总

当咱们写 age = observable.box(12) 的时候,写 @observable age = 12 的时候,写 age = observable(12) 的时候,mobx 作了什么?不知道有多少人仔细研究过,没研究也没关系,这篇文章就是带你去了解,mobx 具体作了什么?api

api/observable.ts 文件

observable.box

observable 上绑定了许多属性,好比经常使用的 boxmaparray。当咱们调用 observable.box 的时候,mobx 会首先判断当前调用方式,若是当前的调用方式会 decorator 调用,则直接报错。函数

if (arguments.length > 2) incorrectlyUsedAsDecorator("box")
复制代码

为何 mobx 能够经过参数个数就能判断出来当前是否为 decorator 调用?那是由于若是经过装饰器调用,会往函数内传入 3 个参数,因此这边经过判断参数个数就能够肯定当前是否为 decorator 调用。源码分析

相信你们都知道 box 方法还有第二个参数 (不单单只是 box 有),这个参数的做用主要用以判断用哪个 enhancername 的值。post

最后返回 ObservableValue 实例。ui

new ObservableValue(value, getEnhancerFromOptions(o), o.name, true, o.equals)
复制代码

@observable

调用 observable 时候,等于调用 createObservablespa

const observable = createObservable
复制代码

createObservable 接收 3 个参数,内部会对第二个参数进行判断,若是为 string,则调用 deepDecorator 函数。3d

observable()

若是传入的参数为已监听对象,则直接返回;若是不是基本数据类型,则根据参数类型调用不一样的包装方法,好比对于 array 调用 observable.array。若是是 NaN,直接返回。若是是基本数据类型,提醒用户使用 observable.box 方法。code


咱们已经知道 mobx 对于咱们的代码会作两件不一样的事,一种调用 deepDecorator 函数,一种实例化 ObservableValue对象

注意,这里咱们只针对于传入的值为 number 类型讨论,不一样类型有不一样的实现方式继承

observable.box

实例化 ObservableValueObservableValue 类继承 Atom 类,ObservableValue 内部重写了 setget 方法。

当访问实例时,会向全局发出 reportObserved 事件,并把当前实例存到 derivation.newObserving 中,以便数据发生更改,通知 derivation。在这里,实例为被观察者,derivation 为观察者。

修改实例值时,会开启事务处理,并向全部的观察者推送这次事件,推送完成后结束事务处理。

究竟 mobx 是如何更新依赖关系?咱们以 autorun 举例。

autorun(()=>{
    console.log(age.get())
})
复制代码

当咱们调用 autorun 时候,会在全局状态中增长当前实例,也就是当前的 derivationautorun 参数执行时,会把 age 的值,也就是 ObservableValue 实例,推入到当前的 derivation 属性中,derivation 会用 diffValue 来刷新当前依赖关系,保持依赖最新。

@observable

调用 createDecoratorForEnhancer 返回值,在原型上添加 __mobxDecorators 对象,此对象的每个属性 ( 比方说 @observable age,这里面的属性就是 age ) 都会存放一些关键信息,并劫持属性的 getset 方法。

target.__mobxDecorators[prop] = {
    prop,
    propertyCreator,
    descriptor,
    decoratorTarget: target,
    decoratorArguments
}
复制代码

当访问属性,会在原型上添加 __mobxDidRunLazyInitializers$mobx$mobx 内存放 ObservableObjectAdministration 实例,并在 $mobx.values 对应的每个属性存放 ObservableValue 实例。

const observable = (adm.values[propName] = new ObservableValue(
    newValue,
    enhancer,
    `${adm.name}.${propName}`,
    false
))
复制代码

并对于属性的访问和读取会再次劫持,每当访问,都会调用原型上 $mobxreadwrite 方法。readwrite 方法所作的事与 observable.box 内部 getset 作的事情同样。

文章列表

相关文章
相关标签/搜索