SaaS管理系统开发经验------Dva(Redux)实战经验分享

写在前面

SaaS 2.1 已经开发结束了,时间早已过去了好几个月,今天若是说从Dva基础入门讲起的话,实在没必要 ,没有比官网上的作者自己的介绍更专业更详尽了,既然这个系列想说的是实战经验,那今天就把Dva 在实战中总结一下,向各位大佬求证一下:

Dva封装了Redux和Redux-saga,最大限度地精简了Redux ,所以在记录实战经验的时候是视他们为一体的。

一些细节

1. Dva的modal是需要注册的。

特别是刚入门Dva的时候,很大可能会遇到由于忘记注册modal而抓狂到怀疑人生的;

    app.model(require('./models/global').default);
复制代码
2. Modal的拆分---业务层还是数据层。
3. effect中的方法是可以跨Modal中调用的,但是要声明命名空间。
export default {
  namespace: 'user',
  state: {
    identity: 0,
    locale:'zh_CN',
  },

  effects: {
    * handleChangeIdentity({ payload, callback }, { call, put }) {
      const response = yield call(getChangeIdentity, payload);
      yield put({ type: 'doChangeIdentity', payload: response.data });
      // 这里通过命名空间account调用 account这个Modal的方法
      yield put({ type: 'account/doChangeIdentity', payload: response.data });
    }
    ...
  }
  
  ...
} 

复制代码
4. 组件中可以直接调用reducer中的方法,来更改Modal中的state,从而刷新页面。

也意味着同一个Modal内effect中的方法名不要和reducer中的方法名重复。

5. effect中的拿state中的数据---select。
effects: {
    * handleChangeIdentity(_, { call, put , select}) {
      // 这里通过select方法拿取state中的数据
      const identity=yield select(state=>state.user.identity);
      const response = yield call(getChangeIdentity, {identity});
      ...
    }
    ...
}

复制代码

注意这里的state不是当前Modal的state,而是最顶层的state

6. Modal中方法命名经验:handle--get/post---do。

由于一个接口请求需要定义三个方法:方法调用effect,执行请求service,改变state reducer,所以为了方便追踪采用effect里使用handleXXX命名,service使用get/postXXX命名, reducer里采用doXXX命名。

从此再也不用为方法太多,命名发愁了

关于使用HashHistory还是BrowserHistory

使用 hashHistory,浏览器上看到的 url 会是这样的: /#/user/hai?pk=ads

使用 browserHistory,浏览器上看到的 url 会是这样的:/user/hai

当然看起来 browserHistory 很好很理想,但 browserHistory 需要 server 端支持,就PWA(单页)应用来讲,是不太合适的, 毕竟单页应用的路由是自己控制的。

而使用hashHistory的时候,因为 url 中 # 符号的存在,从 /#/ 到 /#/user/haishanh 浏览器并不会去发送一次 request, react-router 自己根据 url 去 render 相应的模块。

如果使用 browserHistory 的时候,浏览器从 / 到 /user/haishanh 是会向 server 发送 request 的。 所以 server 端是要做特殊配置的。比如用的 express 的话,你需要 handle 所有的路由 app.get('*', (req, res) => { ... }), 使用了 nginx 的话,nginx也要做相应的配置。

单向数据流之Modal中的state 与组件中的state

安装Redux单向数据流的设计思想,数据流向为:dispatch开始请求数据----->reducer接收数据更新state----->页面刷新,也就是整个项目共同维护一个state树----store,也就是说组件内部不该有state,这样更符合Redux单向数据流思想。开发中发现一些页面临时数据比如一个弹窗显示隐藏都需要dispatch一个action,然后reducer里更新state,要横跨好几文件,开发效率也跟着降低了。所以最后采取了一个折中一点的方法,一些页面内部状态之类的临时数据还是放组件内部State。

除开一些组件临时状态使用本地state,其他state都应该属于全局。

当然这也引入下一个问题:当组件内部状态需要根据后台数据改变时怎么处理?这就是下一个问题....

关于Dva effect回调修改本地state

接上回书:当组件内部状态需要根据后台数据改变时,可以采用回调的方式解决。

  getNotice = () => {
    const { dispatch } = this.props;
    dispatch({
      type: 'workbench/handleGetNotice',
      payload: {
        isRead: 0,
      },
      // 在action传递一个callback方法作为回调
      callback: (data) => {
        this.setState({
            visible:data.isOk
        });
      },
    });
  };
  
  handleGetNotice({ payload,callback }, { call, put }) {
    const response = yield call(getNotice, a);
    // 在收到数据时执行回调方法
    callback&&callback(response.data);
    
  }
  
复制代码

这里特别注意:不要因为这里可以执行回调改变state,而偷懒将state全部放组件里,如此就违背了Redux单向数据流,如此你又何必煞费苦心使用Redux呢?我想Dva作者不会再官网推荐这种写法,大概是因为它确实违背了单向数据流的红线,而我也只是在极其复杂的情况下才用过几次,应急之用罢了。

今天就想到这么多了,以后如果想起别的再来补上吧。也请各位行家里手不吝赐教!

猜你喜欢

转载自juejin.im/post/5c07b899518825371057fa68