谈谈 dva 和 mobx 的使用感觉

在使用 react 的时候或多或少会接触到状态管理,从开始学 react 到如今也挺久了,也用过几种状态管理工具,今天谈一谈这些工具的区别吧。javascript

dva

经朋友推荐开始接触 dva ,从 1.x 版本开始使用,一直看着它发展到前不久的 2.x,我也基于这个工具开发了一套项目模版,它简化了 redux 的使用,而且在封装了 redux-saga 和 react-router,同时还能够包含 dva-loading 插件获取 loading 状态等。html

在 redux 时代,当我须要新增一种跨页面全局数据的时候,我须要去项目的 reducers 目录定义一下这种数据命名和初始值,而后在 constans 目录中为更改这项数据的操做定义一种惟一的操做类型(type),再去 actions 目录定义一些方法,这些方法最后会获得更改后的数据和操做类型(type),最后再回到 reducers 中根据这个操做类型(type)把数据整合到 reducer 中…能够看到,我在编写 redux 这部分代码的时候须要频繁在 actions 、 constants 、 reducers 这几个目录间切换。java

而使用 dva 就能够免除这些困扰了,我只须要一个 model 中就能够完成全部操做:react

// app全局性状态管理
import * as appApis from '../services/app'; // 异步请求接口

export default {
  namespace: 'app',

  state: {
    channels: [],
    show: true
  },

  reducers: {
    getChannelsAndGamesSuccess(state, { channels, games }) {
      return { ...state, channels, games };
    },
    changeShow(state, { show }) {
      return { ...state, show };
    }
  },

  effects: { // 异步
    * getChannelsAndGames(_, { call, put }) {
      const res = yield call(appApis.getChannelsAndGames);
      yield put({
        type: 'getChannelsAndGamesSuccess',
        channels: res.channels
      });
    }
  },
    
  subscriptions: { // 订阅
    setup({dispatch, history}) {
      history.listen(location => {
        if (location.pathname == '/') {
          dispatch({
            type: 'getChannelsAndGames'
          });
        }
      });
    }    
  }
};

这即是一个 model 对象,state 定义数据、effects 中执行异步请求、触发 action 在 reducers 中改变数据,一鼓作气!git

此外它还含有其余特性,好比:subscription(订阅),能够在这里订阅 history 路由变化,进入根路径执行 getChannelsAndGames 获取数据,而不须要在 react 的生命周期中作这些事;用上 dva-loading 插件,在更改数据的过程当中还会自动设置 loading 状态,这在异步请求中很是有用!github

mobx

既然 dva 这么好用,为何还要使用 mobx 呢?还不是为了折腾?,用了才能知道二者的优劣,一样的基于 mobx 我也建立了一个项目模版redux

在使用 dva 的时候,但凡遇到异步请求的时候都须要先定义一个 effects ,请求完成后再触发一个 action 去修改数据,因而,强迫症做怪,这二者的命名老是让我感受难受和啰嗦,你能够看到我都是定义为 getXxxgetXxxSuccessreact-router

action 是修改 state 的惟一途径,是的,全部的状态管理库都是这样的,可是 mobx 经过一些工具函数解决了这一问题:app

// app全局性状态管理
import { observable, action, runInAction } from 'mobx';
import * as appApis from '../services/app';

export default class AppStore {
  @observable show = true;
  @observable list = [];

  @action toggleShow = () => { this.show = !this.show; }
  @action getData = async (params) => {
    try {
      const res = await appApis.getTopicsList(params);
      // await 以后,再次修改状态须要动做: 
      runInAction(() => {
        this.list = res.data;
      });
    } catch (e) {
      console.error(e);
    }
  }
}

/**
 * -----------------------------------------------------------------
 */
// app全局性状态管理
import { observable, action } from 'mobx';
import { asyncAction } from "mobx-utils"
import * as appApis from '../services/app';

export default class AppStore {
  @observable show = true;
  @observable list = [];

  @action toggleShow = () => { this.show = !this.show; }
  @asyncAction * getData(params) { // <- 注意*号,这是一个 generator 函数!
    try {
      const res = yield appApis.getTopicsList(params); // 用 yield 代替 await
      this.list = res.data;
    } catch (e) {
      console.error(e);
    }
  }
}

以上是我最喜欢的两种写法,分别借助了 runInActionasyncAction 这两个工具函数,固然,还有其余方法能够参考。异步

总结

不论是 redux 、 dva ,仍是 mobx ,每种技术的出现都是为了带给咱们更好的开发体验、更高的开发效率,也伴随着不同的学习成本,虽然 mobx 能够治好个人强迫症,可是也反逼我去学习了修饰器;虽然看起来 redux 是最繁琐的,可是它多是对新手最友好的,参考资料也是最多的,也可以一步步让我知道状态是如何改变的,再者,若是我没使用过 redux ,未必能体会到后二者带给我怎样的便利之处。

相关文章
相关标签/搜索