Git Product home page Git Product logo

blog's Introduction

Hi there 👋, I'm Gismanli.

blog's People

Contributors

gismanli avatar

Watchers

 avatar

blog's Issues

MobX 源码学习:Observable

前言

Observable 是 MobX 的重要构成部分,其包含:

  • observable array
  • observable object
  • observable map

也许我们之前会有这样的疑问:为什么我们更改数据时就会触发响应更新呢?

让我们来看一下是具体是如何实现的。

Atom

顾名思义,atom的意思就是原子,在 mobx 中任何可以存储状态的都是一个 Atom。

Atom 有两个重要的职责:

  • 检测它们 被使用 时并报告它们(通过使用 reportObserved),这就建立起了 状态使用运行函数 之间的桥梁。
  • 当它们 改变时 应该通知 mobx,这样 mobx 就可以重新运行使用了该 atom 的函数(derivations)了。

来分析下源代码:

先看下 interface IObservable

export interface IDepTreeNode {
	name: string;
	observing?: IObservable[];
}

export enum IDerivationState {
	NOT_TRACKING = -1,
	UP_TO_DATE = 0,
	POSSIBLY_STALE = 1,
	STALE = 2
}

export interface IDerivation extends IDepTreeNode {
	observing: IObservable[];
	newObserving: IObservable[];
	dependenciesState: IDerivationState;
	runId: number;
	unboundDepsCount: number;
	__mapid: string;
	onBecomeStale();
	recoverFromError(); // TODO: revisit implementation of error handling
}

export interface IObservable extends IDepTreeNode {
	diffValue: number;
	lastAccessedBy: number;
	lowestObserverState: IDerivationState;
	isPendingUnobservation: boolean;
	observers: IDerivation[]; 
	observersIndexes: {}; 
	onBecomeUnobserved();
}

这里预定义了一堆属性,继续看 Atom 定义:

export interface IAtom extends IObservable {
}

export class BaseAtom implements IAtom {
	isPendingUnobservation = true; // for effective unobserving. BaseAtom has true, for extra optimization, so it's onBecomeUnobserved never get's called, because it's not needed
	observers = [];
	observersIndexes = {};

	diffValue = 0;
	lastAccessedBy = 0;
	lowestObserverState = IDerivationState.NOT_TRACKING;

	constructor(public name = "Atom@" + getNextId()) { }

	public onBecomeUnobserved() {
		// noop
	}

	public reportObserved() {
		reportObserved(this);
	}

	public reportChanged() {
		transactionStart("propagatingAtomChange", null, false);
		propagateChanged(this);
		transactionEnd(false);
	}

	toString() {
		return this.name;
	}
}

这里主要是定义了 reportObservedreportChanged 方法:

  • reportObserved: 通过调用这个方法来通知 mobx 该 atom 被使用了。
  • reportChanged:在 mobx 更改信号已通知其所有观察者们失效后调用该方法。

ObservableValue

首先看下类 ObservableValue 的定义:

export type IUNCHANGED = {};

export const UNCHANGED: IUNCHANGED = {};

export interface IObservableValue<T> {
	get(): T;
	set(value: T): void;
	intercept(handler: IInterceptor<IValueWillChange<T>>): Lambda;
	observe(listener: (newValue: T, oldValue: T) => void, fireImmediately?: boolean): Lambda;
}

export class ObservableValue<T> extends BaseAtom implements IObservableValue<T> {
	hasUnreportedChange = false;
	protected value: T = undefined;

	constructor(value: T, protected mode: ValueMode, name = "ObservableValue@" + getNextId()) {
		super(name);
		const [childmode, unwrappedValue] = getValueModeFromValue(value, ValueMode.Recursive);
		// If the value mode is recursive, modifiers like 'structure', 'reference', or 'flat' could apply
		if (this.mode === ValueMode.Recursive)
			this.mode = childmode;
		this.value = makeChildObservable(unwrappedValue, this.mode, this.name);
	}

	public set(newValue: T) {
		const oldValue = this.value;
		newValue = this.prepareNewValue(newValue) as any;
		if (newValue !== UNCHANGED) {
			this.setNewValue(newValue);
		}
	}

	prepareNewValue(newValue): T | IUNCHANGED {
		checkIfStateModificationsAreAllowed();
		const changed = valueDidChange(this.mode === ValueMode.Structure, this.value, newValue);
		if (changed)
			return makeChildObservable(newValue, this.mode, this.name);
		return UNCHANGED;
	}

    setNewValue(newValue: T) {
        const oldValue = this.value;
        this.value = newValue;
        this.reportChanged();
    }

	public get(): T {
		this.reportObserved();
		return this.value;
	}

	public observe(listener: (newValue: T, oldValue: T) => void, fireImmediately?: boolean): Lambda {
		if (fireImmediately)
			listener(this.value, undefined);
		return registerListener(this, listener);
	}

	toJSON() {
		return this.get();
	}

	toString() {
		return `${this.name}[${this.value}]`;
	}
}

Mobx Note

The first

var detailInfo = observable({});
var res = {
    code: 200,
    data: {
        employee: 'GisMan'
    },
    message: "SUCCESS"
}
detailInfo = res;
console.log(detailInfo);

the result is:
image

then:

constructor(props) {
    super(props);
    extendObservable(this, {detailInfo: {}});
    this.detailInfo = {
        code: 200,
        data: {
            employee: 'GisMan'
        },
        message: "SUCCESS"
    };
    console.log(this.detailInfo);
}

or ues dereactor '@observable' in ES.Next

but the detailInfo is:
image

These two are very easy to cause confusion.

In fact, itself is not observable,only properties will be observable

more deatil

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.