observable(可觀察的數據)
數組
import { observable, isArrayLike } from 'mobx'
const arr = observable(['a', 'b', 'c']);
// 觀察以後,數組將不是真正的數組,而是一個Observable數組
console.log(arr, Array.isArray(arr), isArrayLike(arr); // ObservableArray false true
// 可是能夠依然像數組同樣操做數據
console.log(arr[0]); // a
console.log(arr.pop()) // c
對象
const obj = observable({a: 1, b:2});
// 返回的也不是純對象,而是一個被轉化的可被觀察的對象
console.log(obj) //ObservableObjectAdministration
// 一樣也能夠直接對該對象進行讀取
console.log(obj.a, obj.b) // 1 2
// TODU: mobx只能對已有的屬性進行監視,so,在初始化的時候添加可被監視的屬性,若是有倔脾氣的童鞋,我就要新添加的屬性進行監視,你能不能行?笑話,男人怎麼能被說不行呢。若是要調用新添加的屬性呢,使用extendObservable()
Map集合
const map = observable(new Map());
// 一樣也是轉化以後的,可被觀察的map
console.log(map) //ObservableMap
// 一樣也能夠直接調用map方法
map.set('a', 1);
console.log(map.has('a')); // true
map.delete('a');
console.log(map.has('a')); // false
Number、String、Boolean
// Number、String、Boolean原始數據類型須要用observable.box()來包裝可被觀察的變量。
var num = observable.box(20)
var str = observable.box('hello')
var bool = observable.box(true)
console.log(num, str, bool); // 三個都是可被觀察的ObservableValue類型
// 若是要用到原始類型值,須要用observable.get()
console.log(num.get(), str.get(), bool.get()) // 20 'hello' true
// 若是想要修改原始類型值,須要用observable.set()
num.set(50);
str.set('world');
bool.set(false);
console.log(num.get(), str.get(), bool.get()) // 50 'world' false
使用修飾器
class Store {
@observable array = [];
@observable obj = {};
@observable map = new Map();
// 敏感的童鞋可能會問了,誒,不是說原始數據類型用什麼box還有get、set麼,由於mobx爲了簡化Api,在修飾器observable裏作了數據類型判斷。
@observable string = 'hello';
@observable number = 20;
@observable bool = false;
}
觀察數據變化的方式
computed
// 首先引入computed
import { observable, isArrayLike, computed } from 'mobx';
// 用法1
var store = new Store();
var foo = computed(function() {
// 拼接被觀察的兩個數據
return store.string + '/' + store.number;
});
// 當數據改變時,調用此方法
foo.observe(function(change) {
// change表明當前改變的變量值
console.log(change);
});
// 當修改可觀察數據時,會觸發foo.observe
store.string = 'world'
store.number = 30
console.log(foo); // observableValue類型
console.log(foo.get()); // 拼接後的字符串
// 用法2,在store裏直接用修飾器語法使用
class Store {
@observable array = [];
@observable obj = {};
@observable map = new Map();
@observable string = 'hello';
@observable number = 20;
@observable bool = false;
// 經過這個方法,只能獲得最終的計算值,不能獲取observe的方法了
@computed get mixed() {
return store.string + '/' + store.number;
}
}
autorun
// 引用autorun
import { observable, isArrayLike, computed, autorun } from 'mobx';
// 初始化會自動運行,修改autorun中任意可觀察數據可觸發aoturun
autorun(() => {
console.log(store.string + '/' + store.number); // hello/20
});
store.string = 'world'; // world/20
store.number = 30; // world/30
when
// 引入when
import { observable, isArrayLike, computed, autorun, when } from 'mobx';
// when 接收兩個函數,第一個爲布爾值,當只有第一個爲true的時候,纔會執行第二個函數,而且保證最多隻被執行一次。
// TUDU: 第一個參數爲布爾值,必須是一個可觀察數據,不能根據普通變量
// TUDO: 若是一開始就返回真,那麼第二個函數會同步當即執行
when(() => store.bool, () => console.log("it's true"));
store.bool = true; // "it's true"
reaction
// 引入reaction
import { observable, isArrayLike, computed, autorun, when, reaction } from 'mobx';
// 當引入的可觀察數據發生變化時,觸發第二個函數
reaction(() => [store.string, store.number], arr => console.log(arr.join('/')));
store.string = 'world'; // world/20
store.number = 30; // world/30
action
// 引入action
import { observable, isArrayLike, computed, autorun, when, reaction, action } from 'mobx';
class Store {
@observable array = [];
@observable obj = {};
@observable map = new Map();
@observable string = 'hello';
@observable number = 20;
@observable bool = false;
@action bar() {
this.string = 'world';
this.number = 30;
}
}
reaction(() => [store.string, store.number], arr => console.log(arr.join('/')));
// 在action裏修改,這樣reaction只被觸發了一次,提升性能
store.bar(); // world/30
// 使用runInAction方法,一樣只會觸發一次
runInAction(() => {
store.string = 'world';
store.number = 30;
})
mobx-react
PropTypes
// react的PropTypes能夠限制參數的類型,可是可觀察數據類型不是原始類型,因此須要使用mobx-react的PropTypes
// 引入PropTypes 更更名稱,防止和react PropTypes重名
import { PropTypes as ObservablePropTypes } from 'mobx-react'
action propTypes = {
array: ObservablePropTypes.observableArray
}
observer
// 引入observer
import {observer, PropTypes as ObservablePropTypes } from 'mobx-react'
// 不一樣於observable修飾器,它不是修飾類成員的,而是修飾類自己的(react組件類。誰真正的用到了被修改的可觀察數據,誰修重渲染,誰就被observer修飾)
@observer
class Bar extends Conponent {
static propTypes = {
array: ObservablePropTypes.observableArray
};
render() {
const array = this.props.array;
return <div>{array.length}</div>
}
}
經常使用工具函數
toJS
var obj =observable({
x: 1
});
var clone = toJS(obj);
// isObservableObject 判斷是不是observable對象
console.log(isObservableObject(obj)); // true
console.log(isObservableObject(clone)); // false
observe
// 引入observe
import { observe, observable, isArrayLike, computed, autorun, when, reaction, action } from 'mobx';
// 純函數,用於監聽被觀察數據發生變化
constructor() {
// 每次this.list列表發生變化的時候都會觸發回調函數
observe(this.list, change => {
console.log(change)
})
}
spy
// 用於監控全部事件 對可觀察數據的每次修改, 對autorun、reaction的每次觸發
spy(event => {
console.log(event) // 每次都會調用,若是不限制會浪費性能
})