MobX學習之旅

1、MobX

MobX實際上是一個比較輕便的可擴展的狀態管理工具,是一個由Facebook以及一些其餘團隊的人共同維護的開源項目。

當應用公共狀態的組件在狀態發生變化的時候,會自動完成與狀態相關的全部事情,例如自動更新View,自動緩存數據,自動通知server等。
例如React的體系,react + redux + react-redux + redux-saga, view層觸發一個action,中間件會將這個動做進行dispatch,而後reducer執行相應的更新狀態方法,使得store的狀態更新。

MobX官方推薦與React搭配使用,來存儲和更新應用狀態,因此最好搭配mobx-react中間件使用:
原理:
一、React的render是將存儲的狀態轉化爲樹狀結構來渲染組件的方法;
   Mobx是用來存儲和更新狀態的工具;
二、React使用的方法是採用虛擬Dom來進行view視圖的緩存,來減小繁瑣的Dom更新
   而Mobx則經過一個虛擬的狀態依賴圖表來讓react組件和應用狀態同步化來減小沒必要要的狀態來更新組件的

2、MobX與其餘狀態管理工具的區別

一、對比Redux
  conponent-->dispatch(action)-->reducer-->subscribe-->getState-->component
  對比React-Redux
  component-->actionCreator(data)-->reducer-->component
這裏的reducer在MobX裏都給了action,直接經過action來更改狀態,不須要reducer來操做state了,也不需關注reducer純不純了

二、對比Vuex
component-->dispatch(action)-->mutation--(mutate)-->state-->component
vuex中提出了同步mutation和異步action,如今mobx也無需mutaiton,但借鑑了computed這個純函數。

相比這兩個工具,MobX內置了數據變化監聽機制,使得在實際應用的時候一切都是那麼的順其天然。

3、MobX核心模塊

MobX的數據驅動解構:
    action--(update)-->state--(update)-->computed--(trigger)-->reaction
    
MobX與decorater語法結合(註解形式@)結合起來用比較優雅,也算是MobX的一大亮點吧!

Observable

是被觀察着和觀察者的概念,你也能夠理解爲生產者和消費者的概念
@observable/Observable 方法將對象的全部屬性從新克隆成新對象,並將克隆對象轉變成可觀察的。
@observer就是在你訂閱觀察的對象的地方添加註釋來監聽對象的更新

Observable 方法的值能夠是以下類型:

一、object(原型是Object): Observable方法將該對象克隆成新對象並將屬性轉變成可觀察的;
可是後添加的屬性不會變爲可觀察的,須要用到set或者extendObservable;

    eg: 
    @observable car = {color: red; name: 'Infinity'}
    
    注:這也實際上是extendObservable(this,{ car: {color: red; name: 'Infinity'} })的語法糖
    向對象中添加屬性:
    extendObservable(car, {price: '300w'})

二、Array:Observable會建立一個類數組對象來代替真正的數組,而且支持全部的原生方法,
可是sort和reverse有所不一樣,這裏的被觀察的數組對象的這兩個方法,是不會改變數組自己,而是一個拷貝的數組;

三、Es6的Map:建立一個動態建的observable映射,能夠對特定項的更改作出反應等;會返回一個新的Observable Map

四、object(有自身的原型對象):這種狀況須要使用observable.box(value)來管理這樣的值
經過box這個箱子來存這些值,並使用.get()用來獲取當前值,採用.set(newValue)來更新值。

    eg:
    const carName = observable.box('Infinity');
    console.log(carName.get());
    carName.set('ofo');

Computed

是在定義相關的一些數據發生變化的時候自動更新的值,經過@computed來修飾使用;
 注意:computed修飾的是一個狀態,狀態不能重複聲明,只有參與計算的值發生改變纔會觸發computed
 
 例如我須要對數組進行篩選:
 @observable numbersArr = [99, 80, 79, 68, 2, 43, 1, 23];

1、getter
eg:
 // 篩選數組中乘2並大於50的數
  @computed get computedNumbers() {
    return this.numbersArr.filter((item) => {
      return item * 2 > 50;
    }).join(' ');
  }

而後在組件內進行調用:
<div>{this.props.store.computedNumbers}</div>

2、setter

set computedBumbers(value) {
    this.numbersArr = [99, 80, 79, 68, 2, 43, 1, 23];
}

// set方式可使得數據進行逆推導 將數據按照既定的方式進行復原
eg:
  @observable length = 2;
  @computed get squared() {
    return this.length * this.length;
  }
  set squared(value) {
    this.length = Math.sqrt(value);
  }

注:這與autorun還有點區別,若是有一個函數應該自動運行(例如只是爲了達到某種效果/功能),但不會產生一個新的值,那就使用autorun,可是通常這種狀況比較少

Action

比起官方說的「動做」,我更願意稱爲是「行爲」,mobx的action吸取了redux和vuex的數據處理的複雜邏輯
用來修改狀態,不一樣於Computed

eg:
component:
sendInfo = () => {
    const username = this.name.value;
    const pwd = this.pwd.value;

    if (!username || !pwd) {
      return;
    }

    // 調接口
    this.props.testDecStore.handleGetUserInfo();
  };

store:
// 4、異步數據獲取
@action handleGetUserInfo() {
    this.sendCount++;
    testDecService.getUserInfo().then((data) => {
      this.userInfo = data;
   })
}

Autorun

這個函數相似computed,是經過對狀態的更新作出反應,可是不一樣於computed。

computed建立的函數,是有本身的觀察者的,而autorun是隻有它的依賴關係改變時纔會從新計算,
不然它的值被認爲是不相干的。正如官方所說是比較適合log打印日誌,持久化更新UI的代碼,而不是用來產生新的值

接收的參數:
1,對象,
二、delay: 函數延遲執行時間,例如節流去抖
三、name: 
四、onError: 用來處理reaction的錯誤
五、scheduler: 設置自定義調度器以決定如何調度autorun函數的從新運行

eg:
autorun(() => {
    // do something
}, {
    onError(e) {
        alert('error')
    }
})


實例:
autorun(() => {
  this.myname = `my name is ${this.firstName} ${this.lastName}`;
});

changeName = () => {
    this.firstName = `Alice${new Date().getTime()}`;
    this.lastName = `Thomas${new Date().getTime()}`;
 };

<div className="tips" >
  測試autorun
  <span className="btn-span" onClick={this.changeName}>開始</span>
  <div>{this.myname}</div>
</div>
 只要firstname和lastname發生變化都會更新dom

可是,若是僅僅想要在被觀察的變量有變化的時候觸發,而不是當即執行autorun,那麼咱們能夠用到reaction了;vue

Reaction

Reaction是在初次數據變化後纔會觸發

4、Mobx-react核心概念

Observer

是mobx-react包單獨提供的

Observer是用來將React組建轉變成響應式的組件,內部經過mobx.autorun包裝了組件的
render函數,來確保store的數據更新時來刷新組件

@observer 是observer(class ***{})的註解形式,用來觀察組件,
高階組件 @observer class Test extends React.Component{}
無狀態組件 const Test = observer(() => <div>test</div>)

使用inject組件鏈接提供的sotres,他會使得stores能夠做爲組件的props調用
eg:
@inject('testStore')
@observer class Test extends React.Component{}

Provider

Provider函數爲connect函數提供store參數,自己connect函數就是用來鏈接視圖和數據層的方法。

在跟組件外層包一層provider,使得全部的子組件默認均可以拿到state

使用:

import { Provider } from 'mobx-react';
import store from '../stores';

<Provider {...store}>
    ...
</Provider>

inject

引入數據的方式,@inject(stores); 使得數據被自動保存在組件的this.props中

componentWillReact

mobx-react新增的生命週期鉤子,當組件從新render的時候會被觸發,但在初始渲染前是不會被觸發的

onError

mobx-react提供的錯誤鉤子函數來收集錯誤

用法: 

import { onError } from 'mobx-react';
onError((error) => {
    consol.log(error);
})

5、MobX源碼解讀

6、MobX使用注意

相關文章
相關標籤/搜索