- 🔭 I’m currently working on Tencent.
- 📫 How to reach me: [email protected].
blog's Introduction
blog's People
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;
}
}
这里主要是定义了 reportObserved
和 reportChanged
方法:
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);
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
These two are very easy to cause confusion.
In fact, itself is not observable
,only properties will be observable
more deatil
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.