创建一个可被观察的数据结构和响应

Atoms

在某些时候,你可能想要更多的数据结构或者其它可以在 reactive 计算时使用的东西(例如流)。 使用类 Atom 实现这些是非常简单的,Atoms可用于通知 MobX 当某些被观察的数据结构发生变化。 当数据源被使用或不再使用时,MobX 会通知 atom 。

下面的例子演示了如何创建一个可观察的 Clock,它可以用在响应式函数中,并且返回当前时间。 这个 clock 只有当它被观察了才会运行。

此示例演示了 Atom 类的完整API。

import {Atom, autorun} from "mobx";

class Clock {
    atom;
    intervalHandler = null;
    currentDateTime;

    constructor() {
        // creates an atom to interact with the MobX core algorithm
        this.atom =    new Atom(
            // first param: a name for this atom, for debugging purposes
            "Clock",
            // second (optional) parameter: callback for when this atom transitions from unobserved to observed.
            () => this.startTicking(),
            // third (optional) parameter: callback for when this atom transitions from observed to unobserved
            // note that the same atom transitions multiple times between these two states
            () => this.stopTicking()
        );
    }

    getTime() {
        // let MobX know this observable data source has been used
        // reportObserved will return true if the atom is currenlty being observed
        // by some reaction.
        // reportObserved will alos trigger the onBecomeObserved event handler (startTicking) if needed
        if (this.atom.reportObserved()) {
            return this.currentDateTime;
        } else {
            // apparantly getTime was called but not while a reaction is running.
            // So, nobody depends on this value, hence the onBecomeObserved handler (startTicking) won't be fired
            // Depending on the nature
            // of your atom it might behave differently in such circumstances
            // (like throwing an error, returning a default value etc)
            return new Date();
        }
    }

    tick() {
        this.currentDateTime = new Date();
        // let MobX know that this data source has changed
        this.atom.reportChanged();
    }

    startTicking() {
        this.tick(); // initial tick
        this.intervalHandler = setInterval(
            () => this.tick(),
            1000
        );
    }

    stopTicking() {
        clearInterval(this.intervalHandler);
        this.intervalHandler = null;
    }
}

const clock = new Clock();

const disposer = autorun(() => console.log(clock.getTime()));

// ... prints the time each second

disposer();

// printing stops. If nobody else uses the same `clock` the clock will stop ticking as well.

Reactions

Reaction 允许你创建你自己的 'auto runner'。 当函数应该再次运行时,Reaction 会追踪函数和信号,因为一个或多个依赖关系已更改。

这是 autorun 如何使用 Reaction 来定义的代码:

export function autorun(view: Lambda, scope?: any) {
    if (scope)
        view = view.bind(scope);

    const reaction = new Reaction(view.name || "Autorun", function () {
        this.track(view);
    });

    // Start or schedule the just created reaction
    if (isComputingDerivation() || globalState.inTransaction > 0)
        globalState.pendingReactions.push(reaction);
    else
        reaction.runReaction();

    return reaction.getDisposer();
}