MobX的简单了解

MobX

MobX 是一种简单、可扩展的状态管理,猪齿鱼框架就是用它进行状态管理。

简单理解

mobx修饰组件就是把这个全局的跟组件内的state做关联,全局的变了,局部的也变了,进而触发局部的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 使用:设置可观察数据:使用mobx的observable方法使定义的状态值可以被观察,
    observable 是一种让数据的变化可以被观察的方法,值可以是 JS原始数据类型、引用类型、普通对象、类实例、数组和映射。
  import { observable, autorun } from 'mobx';
  // JS原始类型(Number/String/Boolean)
  const value = observable(0);
  const number = observable(100);
  autorun(() => {
    console.log(value.get());
  }); // 当观测到的数据发生变化的时候,如果变化的值处在autorun中,那么autorun就会自动执行。
  value.set(1);
  value.set(2);
  number.set(101);  // 依次打印 0 1 2

  // 数组、对象类型
  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. 响应可观察数据的变化:
  • (@)computed:监听相关状态变化时自动更新的值。
  const number = observable(10);
  const plus = computed(() => number.get() > 0);

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

  number.set(-19); // number的值变化,触发computed,输出false
  number.set(-1); // number的值变化,因为-1<0,没有改变plus的值,没有输出
  number.set(1); // number的值变化,因为1>0, 输出true
  • autorun:修改autorun中任意一个可观察数据即可触发自动运行
    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 区别:
@computed:用于响应式的产生一个可以被其他 observer 使用的值。
autorun:不产生新的值,而是达到一个效果(如:打印日志,发起网络请求等命令式的副作用),autorun 默认会执行一次,以获取哪些可观察数据被引用。autorun 的作用是在可观察数据被修改之后,自动去执行依赖可观察数据的行为。
@computed:如果一个计算值不再被观察了,MobX 可以自动地将其垃圾回收,而 autorun 中的值必须要手动清理才行。

  1. 修改可观察数据
  • action: 修改状态的行为,使用 action 的好处是能将多次修改可观察状态合并成一次,从而减少触发 autorun 或者 reaction 的次数。
  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只能影响正在运行的函数,而无法影响当前函数调用的异步操作。
    在回调中需要使用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中触发的回调函数,被action给包裹了,action无法影响当前函数调用的异步操作,而回调函数是一个异步操作,所以必须再用一个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可以立刻被执行。

结合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 (
        

{newState.num}

) } }

这里定义了一个类MyState,包括可以被观察的num变量和action函数来改变num,实例化这个类并在组件中使用,使用@observer修饰App组件,组件中可以改变和观察num的值。

跨组件交互

在不使用状态管理的React要实现跨组件交互,通常需要我们在父组件定义state和修改state的函数,然后再通过props传给不同的组件,这样看起来逻辑简单,但在业务很复杂的情况下就会很繁琐,而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) => 
num1 + num2 = {props.store.total}
); const Main = observer((props) => (

num1 = {props.store.num1}

num2 = {props.store.num2}

)); @observer export default class App extends React.Component { render() { return (
); } }

上面的一段代码很好的解释了跨组件交互:Main和AllNum是两个不相关的组件,在MyState中存放组件共同需要的状态和函数,通过props将状态和函数传给两个子组件,子组件可以调用方法改变相应的状态的值。

你可能感兴趣的:(MobX的简单了解)