MobX的簡單了解

MobX

MobX 是一種簡單、可擴展的狀態(tài)管理,豬齒魚框架就是用它進行狀態(tài)管理。

簡單理解

mobx修飾組件就是把這個全局的跟組件內的state做關聯(lián),全局的變了,局部的也變了,進而觸發(fā)局部的render。

安裝

  • 安裝: npm install mobx --save;
  • React 綁定庫: npm install mobx-react --save;
  • mobx相關依賴:npm i babel-plugin-transform-class-properties -D用來編譯類(class)
    npm i babel-plugin-transform-decorators-legacy -D 用來編譯裝飾器
    npm install --save-dev @babel/plugin-proposal-decorators 裝飾器

webpack.config.js 添加如下配置

  rules: [{
    test: /\.js$/,
    exclude: /node_modules/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env','react'],
        plugins: ['transform-decorators-legacy', 'transform-class-properties']
      }
    }
  }]

在react-app項目下支持裝飾器的解決方法

在根目錄下面新建.babelr文件,寫入:

  {
    "presets": ["@babel/preset-env"],
    "plugins": [
      ["@babel/plugin-proposal-decorators", { "legacy": true }],
      ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ]
  }

常用api

  1. observable 使用:設置可觀察數(shù)據:使用mobx的observable方法使定義的狀態(tài)值可以被觀察,
    observable 是一種讓數(shù)據的變化可以被觀察的方法,值可以是 JS原始數(shù)據類型、引用類型、普通對象、類實例、數(shù)組和映射。
  import { observable, autorun } from 'mobx';
  // JS原始類型(Number/String/Boolean)
  const value = observable(0);
  const number = observable(100);
  autorun(() => {
    console.log(value.get());
  }); // 當觀測到的數(shù)據發(fā)生變化的時候,如果變化的值處在autorun中,那么autorun就會自動執(zhí)行。
  value.set(1);
  value.set(2);
  number.set(101);  // 依次打印 0 1 2

  // 數(shù)組、對象類型
  const list = observable([1, 2, 4]);
  list.push(5) 
  console.log(list[0], list[1], list[2], list[3]) // 1 2 4 5

  const obj = observable({a: '11', b: '22'})
  obj.a = "leo";
  console.log(obj.a, obj.b) // leo 22

  // 映射(Map)類型
  const map = observable.map({ key: "value"});
  map.set("key", "new value");
  console.log(map.has('key'))  // true

@observable 使用: 使用裝飾器 @observable 來將其轉換成可觀察的。

  @observer export default class PictureShow extends React.Component {}
  1. 響應可觀察數(shù)據的變化:
  • (@)computed:監(jiān)聽相關狀態(tài)變化時自動更新的值。
  const number = observable(10);
  const plus = computed(() => number.get() > 0);

  autorun(() => {
    console.log(plus.get());
  });

  number.set(-19); // number的值變化,觸發(fā)computed,輸出false
  number.set(-1); // number的值變化,因為-1<0,沒有改變plus的值,沒有輸出
  number.set(1); // number的值變化,因為1>0, 輸出true
  • autorun:修改autorun中任意一個可觀察數(shù)據即可觸發(fā)自動運行
    import { observable, autorun } from 'mobx'
    class Store {
        @observable str = 'leo';
        @observable num = 123;
    }

    let store = new Store()
    autorun(() => {
        console.log(`${store.str}--${store.num}`)
    })
    // leo--123

computed 與 autorun 區(qū)別:
@computed:用于響應式的產生一個可以被其他 observer 使用的值。
autorun:不產生新的值,而是達到一個效果(如:打印日志,發(fā)起網絡請求等命令式的副作用),autorun 默認會執(zhí)行一次,以獲取哪些可觀察數(shù)據被引用。autorun 的作用是在可觀察數(shù)據被修改之后,自動去執(zhí)行依賴可觀察數(shù)據的行為。
@computed:如果一個計算值不再被觀察了,MobX 可以自動地將其垃圾回收,而 autorun 中的值必須要手動清理才行。

  1. 修改可觀察數(shù)據
  • action: 修改狀態(tài)的行為,使用 action 的好處是能將多次修改可觀察狀態(tài)合并成一次,從而減少觸發(fā) autorun 或者 reaction 的次數(shù)。
  import { observable, computed, reaction, action} from 'mobx';

  class Store {
    @observable string = 'leo';
    @observable number = 123;
    @action bar(){
      this.string = 'pingan'
      this.number = 100
    }
  }
  let store = new Store()
  reaction(() => [store.string, store.number], arr => {
    console.log(arr)
  })
  store.bar() // ["pingan", 100]
  • runInAction(name?, thunk):action只能影響正在運行的函數(shù),而無法影響當前函數(shù)調用的異步操作。
    在回調中需要使用action進行包裹,這里借用官網給出的例子:
  @action createRandomContact() {
  this.pendingRequestCount++;
  superagent
    .get('https://randomuser.me/api/')
    .set('Accept', 'application/json')
    .end(action("createRandomContact-callback", (error, results) => {
      if (error)
        console.error(error);
      else {
        const data = JSON.parse(results.text).results[0];
        const contact = new Contact(this, data.dob, data.name, data.login.username, data.picture);
        contact.addTag('random-user');
        this.contacts.push(contact);
        this.pendingRequestCount--;
      }
  }));
}

在end中觸發(fā)的回調函數(shù),被action給包裹了,action無法影響當前函數(shù)調用的異步操作,而回調函數(shù)是一個異步操作,所以必須再用一個action來包裹住它,這樣程序才不會報錯。
如果使用async function來處理,可以使用runInAction這個API來解決之前的問題。

  import {observable, action, useStrict, runInAction} from 'mobx';
  useStrict(true);

  class Store {
    @observable name = '';
    @action load = async () => {
      const data = await getData();
      runInAction(() => {
        this.name = data.name;
      });
    }
  }

調用load之后,runInAction可以立刻被執(zhí)行。

結合react使用

  import React from 'react';
  import { observable, useStrict, action } from 'mobx';
  import { observer } from 'mobx-react';
  useStrict(true);

  class MyState {
    @observable num = 0;
    @action addNum = () => {
      this.num++;
    };
  }

  const newState = new MyState();

  @observer
  export default class App extends React.Component {

    render() {
      return (
        <div>
          <p>{newState.num}</p>
          <button onClick={newState.addNum}>+1</button>
        </div>
      )
    }
  }

這里定義了一個類MyState,包括可以被觀察的num變量和action函數(shù)來改變num,實例化這個類并在組件中使用,使用@observer修飾App組件,組件中可以改變和觀察num的值。

跨組件交互

在不使用狀態(tài)管理的React要實現(xiàn)跨組件交互,通常需要我們在父組件定義state和修改state的函數(shù),然后再通過props傳給不同的組件,這樣看起來邏輯簡單,但在業(yè)務很復雜的情況下就會很繁瑣,而Mobx可以更加簡單的解決問題。

  class MyState {
    @observable num1 = 0;
    @observable num2 = 100;

    @action addNum1 = () => {
      this.num1 ++;
    };
    @action addNum2 = () => {
      this.num2 ++;
    };
    @computed get total() {
      return this.num1 + this.num2;
    }
  }

  const newState = new MyState();

  const AllNum = observer((props) => <div>num1 + num2 = {props.store.total}</div>);

  const Main = observer((props) => (
    <div>
      <p>num1 = {props.store.num1}</p>
      <p>num2 = {props.store.num2}</p>
      <div>
        <button onClick={props.store.addNum1}>num1 + 1</button>
        <button onClick={props.store.addNum2}>num2 + 1</button>
      </div>
    </div>
  ));

  @observer
  export default class App extends React.Component {

    render() {
      return (
        <div>
          <Main store={newState} />
          <AllNum  store={newState} />
        </div>
      );
    }
  }

上面的一段代碼很好的解釋了跨組件交互:Main和AllNum是兩個不相關的組件,在MyState中存放組件共同需要的狀態(tài)和函數(shù),通過props將狀態(tài)和函數(shù)傳給兩個子組件,子組件可以調用方法改變相應的狀態(tài)的值。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1. 介紹 1.1. 原理 React的render是 狀態(tài) 轉化為樹狀結構的渲染組件的方法而MobX提供了一種存...
    三月懶驢閱讀 12,938評論 1 28
  • 寫的都是自己的一些感受=。=可能都是野路子=。=大牛就別看了=。=代碼:https://github.com/Xi...
    無星灬閱讀 2,126評論 5 1
  • MobX 簡單、可擴展的狀態(tài)管理(可觀察的數(shù)據) 使用: 安裝: npm install mobx --save。...
    jevons_lee_閱讀 750評論 0 1
  • Mobx解決的問題 傳統(tǒng)React使用的數(shù)據管理庫為Redux。Redux要解決的問題是統(tǒng)一數(shù)據流,數(shù)據流完全可控...
    光哥很霸氣閱讀 13,187評論 2 21
  • 忙忙碌碌幾周,今天終于有時間靜下來寫點東西。說起寫作,我沒有在喧囂中寫作的能力?!按箅[隱于市”的風格不適合我,我只...
    我類林妹妹閱讀 187評論 0 0

友情鏈接更多精彩內容