第一次浏览源码,可能有了解的不太正确的中央心愿大佬们能帮我纠正。开始看的是6,起初看到observable发现和5的差距还是有一点的,所以在所以“autorun”的局部可能会有6的源码,但差距并不大。

1.mobx的基本概念

Observable 被观察者

Observer 察看

Reaction 响应

var student = mobx.observable({    name: '张三',});mobx.autorun(() => {    console.log('张三的名字:', student.name);});

2.mobx的原理

1.在响应式函数中(如以上autorun中通常会拜访一个或多个observable对象),

  • 1)autorun首先创立一个Reaction类型的实例对象reaction,通过参数track一个响应式函数的回调函数。
  • 2)而后执行reaction.schedule_办法,执行回调函数,回调函数中调用被观察者observable.get办法,触发reportObserved办法。
  • 3)reportObserved办法中会将observavle对象收集到globalState.trackingDerivation.newObserving_队列中(globalState.trackingDerivation此时等同于reaction对象)
  • 4)解决reaction和observable的依赖关系,遍历reaction.newObserving_属性,在newObserving_队列中的每一个observable.observers_属性中增加以后reaction对象。

2.被观察者observable的value发生变化,调用observable对象set办法,触发propagateChange办法。propagateChange办法中,遍历observable.observers_属性顺次执行reaction.onBecomeStale办法,再次将以上的2)3)4)执行一遍。

3.源码解读–autorun

以下为删减后的代码

3.1 autorun

export function autorun(    view: (r: IReactionPublic) => any,// autoruan函数的回调函数    opts: IAutorunOptions = EMPTY_OBJECT): IReactionDisposer {        const name: string = "Autorun"    const runSync = !opts.scheduler && !opts.delay        // 首先创立一个Reaction类型的对象 次要性能是用来管制工作的执行    let reaction = new Reaction(        name,        function (this: Reaction) {            this.track(reactionRunner)        },        opts.onError,        opts.requiresObservable    )    function reactionRunner() { view(reaction) } // view即autorun函数的回调    reaction.schedule_() // 立刻执行一次部署            return reaction.getDisposer_() // 用于在执行期间清理 autorun}

从上边的源码能够看出autorun次要做了一下三个动作

  • 1)创立一个Reaction类型的对象 次要性能是用来管制工作的执行
  • 2)将view即auto的回调函数,调配给reaction.track
  • 3)立刻执行一次部署 ,此时你应该了解文档中所说的“当应用autorun时,所提供的函数总是立刻被触发”

3.2 reaction.schedule_的源码

schedule_() {    if (!this.isScheduled_) {        this.isScheduled_ = true        globalState.pendingReactions.push(this) // 以后的reaction对象入列        runReactions() // 队列中的所有reaction对象执行runReaction_办法    }}function runReactionsHelper() {   let remainingReactions = allReactions.splice(0)   for (let i = 0, l = remainingReactions.length; i < l; i++)        remainingReactions[i].runReaction_()}

schedule_办法做了两件事

  • 1)以后的reaction对象入列
  • 2)队列中的所有reaction对象执行runReaction_办法

3.3 runReaction_源码

runReaction_() {    startBatch() // 开启一层事务    this.isScheduled_ = false       if (shouldCompute(this)) {// derivation.dependenciesState_默认为-1 (未跟踪)        this.onInvalidate_()    }    endBatch() // 敞开一层事务 startBatch和endBatch总是成对呈现}

翻看上边的代码能够发现onInvalidate_是在初始化Reaction时传入构造函数的,实际上时调用了reaction.track办法

track(fn: () => void) {    startBatch()    ...    const result = trackDerivedFunction(this, fn, undefined) // 执行工作 更新依赖    ...    endBatch()}

3.4 track办法次要是调用了trackDerivedFunction

export function trackDerivedFunction<T>(derivation: IDerivation, f: () => T, context: any) {    ...    globalState.trackingDerivation = derivation  // 将derivation(此处等同于reaction对象)挂载到全局变量 这样其余成员也可拜访此derivation    ...    // 执行reaction传递的的回调办法,翻看代码能够看出执行的是autoran函数的回调办法    // 回调中个别会调用一或多个observable对象,触发observable.get办法,再触发reportObserved办法    let result = f.call(context)    ...    globalState.trackingDerivation = prevTracking    bindDependencies(derivation) // 更新observable和raction的依赖关系    return result}

执行因为autorun回调用到了student.name变量,这里的"."其实就是get操作;一旦设计到get操作,监督这个name的属性的观察员就会执行reportObserved办法(后边介绍Oobservable时候会重点介绍这里)。

3.5 reportObserved源码

export function reportObserved(observable: IObservable): boolean {    ...    const derivation = globalState.trackingDerivation    if (derivation !== null) {        if (derivation.runId_ !== observable.lastAccessedBy_) {                         // 更被观察者的lastAccessedBy_属性(事务id),这个是为了防止反复操作            observable.lastAccessedBy_ = derivation.runId_                         // 更新derivation(此处为reaction)的newObserving属性,将被观察者退出该队列中            // 后续derivation和observable更新依赖关系就靠这个属性            derivation.newObserving_![derivation.unboundDepsCount_++] = observable             ...        }        return true    } else if (observable.observers_.size === 0 && globalState.inBatch > 0) {        queueForUnobservation(observable)    }    return false}

上边的代码,咱们次要关注影响derivation的操作

  • 1)更新observable的lastAccessedBy_属性(事务id),这个是为了防止反复操作。
  • 2)更新derivation(此处为reaction)的newObserving属性,将observable退出该队列中,后续derivation和observable更新依赖关系就靠这个属性

随后autorun的工作执行实现后,derivation就开始着手更新和被观察者observable的依赖关系

3.6 bindDependencies源码

function bindDependencies(derivation: IDerivation) {    const prevObserving = derivation.observing_         // derivation.newObserving_为derivation依赖的observable对象的队列    const observing = (derivation.observing_ = derivation.newObserving_!)    let lowestNewObservingDerivationState = IDerivationState_.UP_TO_DATE_ // 默认为0    let i0 = 0,        l = derivation.unboundDepsCount_    for (let i = 0; i < l; i++) {        /**         * 以下是一个去重的过程          * observable.diffValue_默认是0         * 循环时候置为1,因为observing为Observable类型的对象数组,所以不同地位上雷同的值的diffValue_都会变成1         * 在遍历到反复项后就不会进入下边的判断,i0就不会++         * 遍历到非反复项(diffValue_为0的项),则间接将此项填充到i0对应的地位上         * 这样数组循环结束,i0即非反复项的数量,observing.length = i0即删除掉了多余项         */                const dep = observing[i]        if (dep.diffValue_ === 0) {            dep.diffValue_ = 1            if (i0 !== i) observing[i0] = dep            i0++        }    }    observing.length = i0    derivation.newObserving_ = null // newObserving 置空    /**     * prevObserving中和observing中存在的均为observable对象      * 此时如果在上边的循环实现后 observing存在的observable对象的diffValue_均为1     * 在prevObserving队列如果是diffValue_依然为0,示意以后derivation曾经不依赖此observable对象     */    l = prevObserving.length    while (l--) {        const dep = prevObserving[l];        if (dep.diffValue_ === 0) {            // 将以后derivation已不再依赖此observable对象,将其从observable.observers_中的deleted掉            removeObserver(dep, derivation)          }        dep.diffValue_ = 0 // 将prevObserving队列中的observable的diffValue_均置为0    }        while (i0--) {        const dep = observing[i0]                // observing依然为1的阐明此observable对象不在prevObserving队列中         if (dep.diffValue_ === 1) {            dep.diffValue_ = 0            // 在observable.observers_中增加以后的derivation对象            addObserver(dep, derivation)         }    }    // 通过以上的3次循环,将derivation.observing更新为最新的依赖(并去重),    // 并在曾经不依赖的observable对象的observers_中delete以后的derivation对象    // 在新建设起的依赖的observable对象的observers_中add以后的derivation对象}

响应被观察者observable对象的value发生变化
上边提及,一旦observable的value发生变化,就会触发observable.get办法,而后触发propagateChange办法,propageateChange源码如下

export function propagateChanged(observable: IObservable) {    ...    observable.observers_.forEach(d => {        ...            d.onBecomeStale_()        ...    })    }

observable.observers_存储的是,与observable对象有依赖关系的derivation对象,在propagateChanged办法中,遍历observers_执行derivation对象的onBecomeStale_办法,咱们来看一下onBecomeStale_的源码

3.7 onBecomeStale_的源码

onBecomeStale_() {    this.schedule_()}

this.schedule_是不是很相熟,翻一下上边的代码,发现是在autorun函数中创立reaction对像的时候调用了reaction.schedule_()。所以这下明确propagateChanged调用onBecomeStale_是让reaction再次执行一次之前的部署操作(也就是执行autorun的回调,解决依赖关系);

4.接下来开始看observable(被观察者)局部

4.1 observable的别名createObservable

export const observable: IObservableFactory &    IObservableFactories & {        enhancer: IEnhancer<any>    } = createObservable as any // observable的别名createObservable// 将observableFactories的属性复制一份给observableObject.keys(observableFactories).forEach(name => (observable[name] = observableFactories[name]))
  • 1)首先 observable 是函数函数同 createObservable。
  • 2)observable复制了observableFactories的属性。
function createObservable(v: any, arg2?: any, arg3?: any) {    // @observable someProp;    if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") {        return deepDecorator.apply(null, arguments as any)    }    // it is an observable already, done    if (isObservable(v)) return v    // something that can be converted and mutated?    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    // this value could be converted to a new observable data structure, return it    if (res !== v) return res}

createObservable办法起到了转发的作用,将传入的对象转发给具体的转换函数。
简略剖析一下具体的转化模式

  • 1)arguments[1] === “string” || typeof arguments[1] === “symbol” 采纳的是装璜器@observable,装璜器的参数(target,prop,descriptor)其中arguments[1] 也就是prop为属性名称为字符串类型
  • 2)isObservable(v) 曾经转换为察看值了不须要再转换
  • 3)observable.object、observable.array、observable.map、observable.set依据传入参数的类型别离调用具体的转换方法
  • 4)针对原始类型提醒用户倡议应用observable.box办法

4.2 observable.box

observable.box在文档中是这样介绍的。

observable.box把一般的值转换成可察看的值,如下例。

const name = observable.box("张三");console.log(name.get());// 输入 '张三'name.observe(function(change) {    console.log(change.oldValue, "->", change.newValue);});name.set("李四");// 输入 '张三 -> 李四'

observable.box retrun 一个ObservableValue类型的对像。

box<T = any>(value?: T, options?: CreateObservableOptions): IObservableValue<T> {    const o = asCreateObservableOptions(options) // 格式化入参    // ObservableValue的领有办法get set observe intercept...    return new ObservableValue(value, getEnhancerFromOptions(o), o.name, true, o.equals)},

案例中的“name.set(“李四”)”,就是调用了ObservableValue的set办法。一会再介绍ObservableValue的时候会重点说下。

4.3 外围类 ObservableValue

ObservableValue 继承了 Atom原子类,先梳理一下Atom和ObservableValue和有什么次要能力。

Atom public reportObserved(): boolean {    return reportObserved(this)}public reportChanged() {    startBatch()    propagateChanged(this)   endBatch()}ObservableValuepublic set(newValue: T) {    const oldValue = this.value    newValue = this.prepareNewValue(newValue) as any    if (newValue !== globalState.UNCHANGED) {        const oldValue = this.value        this.value = newValue        this.reportChanged()        ...    }}public get(): T {    this.reportObserved()    return this.dehanceValue(this.value)}interceptobserve

其中reportObserved、propagateChanged在梳理autorun的时候介绍过。

  • 1)reportObserved:调用察看值是用于更新derivation和observable的依赖关系。
  • 2)propagateChanged:察看值扭转时,observable对象的observers中存储的derivation,执行onBecomeStale办法,从新执行部署操作。
  • 3)Observablevalue的set 批改value同时调用Atom的reportChanged办法触发propagateChanged。
  • 4)Observablevalue的get 获取value值的同时调用Atom的reportObserved办法触发reportObserved。

所以上边案例中“name.set(“李四”);”会触发propagateChanged办法,会执行有依赖关系的 derivation 从新执行部署操作

接下来看一下new ObservableValue的时候干了什么?

constructor(    value: T,    public enhancer: IEnhancer<T>,    public name = "ObservableValue@" + getNextId(),    notifySpy = true,    private equals: IEqualsComparer<any> = comparer.default) {    ...    this.value = enhancer(value, undefined, name)}

ObservableValue的构造函数中调用enhancer对value进行了解决,enhancer是通过参数是创立ObservableValue类型对象是传递的参数getEnhancerFromOptions(o)。getEnhancerFromOptions默认返回的是deepEnhancer。

function getEnhancerFromOptions(options: CreateObservableOptions): IEnhancer<any> {    return options.defaultDecorator        ? options.defaultDecorator.enhancer        : options.deep === false        ? referenceEnhancer        : deepEnhancer}

gdeepEnhancer次要内容如下。

export function deepEnhancer(v, _, name) {    if (isObservable(v)) return v    if (Array.isArray(v)) return observable.array(v, { name })    if (isPlainObject(v)) return observable.object(v, undefined, { name })    if (isES6Map(v)) return observable.map(v, { name })    if (isES6Set(v)) return observable.set(v, { name })    return v}

这个deepEnhancer是不是看上去有点眼生,往上翻一下能够看出他和createObservable 函数十分相似,起到了转发的作用,将传入的对象转发给具体的转换函数。所以要了解observable我门次要就是要理解这些转换函数。接下来咱们次要剖析observable.object。

4.4 observable.object

object<T = any>(        props: T,        decorators?: { [K in keyof T]: Function },        options?: CreateObservableOptions    ): T & IObservableObject {      const o = asCreateObservableOptions(options)    if (o.proxy === false) {        return extendObservable({}, props, decorators, o) as any    } else {        const defaultDecorator = getDefaultDecoratorFromObjectOptions(o)        const base = extendObservable({}, undefined, undefined, o) as any        const proxy = createDynamicObservableObject(base)        extendObservableObjectWithProperties(proxy, props, decorators, defaultDecorator)        return proxy    }}

o.proxy为true的时候只是多了一步Proxy,其余的工作根本类似,所以次要关注extendObservable办法就能够了。

extendObservable中调次要用了getDefaultDecoratorFromObjectOptions、asObservableObject、extendObservableObjectWithProperties办法。因为getDefaultDecoratorFromObjectOptions与extendObservableObjectWithProperties有关联,所以先来看asObservableObject,再看另外两个办法。

4.5 extendObservable

export function extendObservable<A extends Object, B extends Object>(    target: A,    properties?: B,    decorators?: { [K in keyof B]?: Function },    options?: CreateObservableOptions): A & B {    options = asCreateObservableOptions(options)    const defaultDecorator = getDefaultDecoratorFromObjectOptions(options) // 默认返回deepDecorator装璜器    asObservableObject(target, options.name, defaultDecorator.enhancer) // make sure object is observable, even without initial props    if (properties)        extendObservableObjectWithProperties(target, properties, decorators, defaultDecorator)    return target as any}

4.6 asObservableObject

asObservableObject办法:

  • 1)创立一个对象amd为ObservableObjectAdministration类的实例。
  • 1)amd赋值给target[$mobx]
  • 2)返回amd;
export function asObservableObject(    target: any,    name: PropertyKey = "",    defaultEnhancer: IEnhancer<any> = deepEnhancer): ObservableObjectAdministration {    const adm = new ObservableObjectAdministration(        target,        new Map(),        stringifyKey(name),        defaultEnhancer    )    addHiddenProp(target, $mobx, adm)    return adm}

4.7 extendObservableObjectWithProperties

extendObservableObjectWithProperties:循环原始对象,对每一个属性值通过都decorator函数解决(decorators办法即通过getDefaultDecoratorFromObjectOptions办法获取的默认为deepDecorator,所以一回间接看deepDecorator)

export function extendObservableObjectWithProperties(    target,    properties, // 原对象    decorators,    defaultDecorator) {    startBatch()    const keys = ownKeys(properties)        // 循环原对象    for (const key of keys) {        const descriptor = Object.getOwnPropertyDescriptor(properties, key)!        const decorator =            decorators && key in decorators                ? decorators[key]                : descriptor.get                ? computedDecorator                : defaultDecorator        const resultDescriptor = decorator!(target, key, descriptor, true) // 通过装璜器解决        if (            resultDescriptor // otherwise, assume already applied, due to `applyToInstance`        )            Object.defineProperty(target, key, resultDescriptor)    }    endBatch()}

4.8 decorator

decorator默认为deepDecorator,咱们来看一下它都干了什么。

export function createDecoratorForEnhancer(enhancer: IEnhancer<any>): IObservableDecorator {    const decorator = createPropDecorator(        true,        (            target: any,            propertyName: PropertyKey,            descriptor: BabelDescriptor | undefined,            _decoratorTarget,            decoratorArgs: any[]        ) => {            const initialValue = descriptor                ? descriptor.initializer                    ? descriptor.initializer.call(target)                    : descriptor.value                : undefined                // 调用target[$mobx].addObservableProp办法            asObservableObject(target).addObservableProp(propertyName, initialValue, enhancer)        }    )    const res: any = decorator    res.enhancer = enhancer    return res}

4.9 addObservableProp办法

decorator中调用了target[$mobx].addObservableProp办法

addObservableProp(    propName: PropertyKey,    newValue,    enhancer: IEnhancer<any> = this.defaultEnhancer) {    const { target } = this    if (hasInterceptors(this)) {        // 拦挡解决        const change = interceptChange<IObjectWillChange>(this, {            object: this.proxy || target,            name: propName,            type: "add",            newValue        })        if (!change) return // 拦截器返回空的时候不须要从新疏忽此次批改。        newValue = (change as any).newValue    }    // newValue转换成ObservableValue类型    const observable = new ObservableValue(        newValue,        enhancer,        `${this.name}.${stringifyKey(propName)}`,        false    )    this.values.set(propName, observable) // 存储    newValue = (observable as any).value         // generateObservablePropConfig办法返回以下描述符    // { ..., get() { return this[$mobx].read(propName)  }, set(v) { this[$mobx].write(propName, v) } }    Object.defineProperty(target, propName, generateObservablePropConfig(propName)) // target生成propName属性    const notify = hasListeners(this)    const change = {          type: "add",          object: this.proxy || this.target,          name: propName,          newValue      }    this.keysAtom.reportChanged() // this.keysAtom即Atom的实例}

addObservableProp办法

  • 1)调用ObservableValue类将newValue转换为可察看值(还记不记得上边ObservableValue调用通过enhancer调用了observable.object办法吗。当初能够看出observable.object办法中在循环对象的属性时又调用了ObservableValue。通过这种递归的形式将对象的属性转换为可察看值)
  • 2)将属性key和observable存入target[$mobx].values中
  • 3)将原对象属性值增加到target,并通过描述符中get和set都是间接调用this[mobx].read和this[mobx].write办法。
  • 4)调用原子类Atom的reportChanged,让依赖此observable对象的derivation从新执行部署操作。

综上extendObservableObjectWithProperties作用即循环原始对象,执行以上4步,实现了将原始对象的属性代理到target上,并将值转换到可察看值,存储在target[$mobx].values中。

4.10 read和write

read(key: PropertyKey) {    return this.values.get(key)!.get()} // observable.get办法 public get(): T {    this.reportObserved() // Atom下的reportObserved    return this.dehanceValue(this.value)}

read办法会依据属性名称从this.values中查找,获取到对应的observable对象再调用observable.get办法触发reportObserved

write(key: PropertyKey, newValue) {    const instance = this.target    const observable = this.values.get(key)    // intercept    if (hasInterceptors(this)) {        const change = interceptChange<IObjectWillChange>(this, {            type: "update",            object: this.proxy || instance,            name: key,            newValue        })        if (!change) return        newValue = (change as any).newValue    }    newValue = (observable as any).prepareNewValue(newValue)    if (newValue !== globalState.UNCHANGED) {        (observable as ObservableValue<any>).setNewValue(newValue)    }}// observable.prepareNewValue和observable.setNewValue办法private prepareNewValue(newValue): T | IUNCHANGED {    if (hasInterceptors(this)) {        const change = interceptChange<IValueWillChange<T>>(this, {            object: this,            type: "update",            newValue        })        if (!change) return globalState.UNCHANGED        newValue = change.newValue    }    // apply modifier    newValue = this.enhancer(newValue, this.value, this.name) // 调用enhancer转换为可察看模式    return this.equals(this.value, newValue) ? globalState.UNCHANGED : newValue}setNewValue(newValue: T) {    const oldValue = this.value    this.value = newValue    this.reportChanged()    if (hasListeners(this)) {        notifyListeners(this, {            type: "update",            object: this,            newValue,            oldValue        })    }}

write办法

  • 1)调用observable.prepareNewValue办法将新的value进行转换
  • 2)调用observable.setNewValue从新批改值
  • 3)触发reportChanged办法。

4.11 综上总结

var student = mobx.observable({    name: '张三',});

mobx通过observable办法用target代理了传入的对象,赋值给student。
因而student的构造应该如下

在调用student.name时候触发会调用get=>read=>observableValue.get=>reportObserved
批改的时候 set=>write=>observableValue.setNewValue=>reportChanged

当初根本能够了解observable是autoruan之间的关系了。