mobx 入門

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) // 每次都會調用,若是不限制會浪費性能
})
相關文章
相關標籤/搜索