(应用)企业后台系统敏捷开发-dva

什么是dva

dva 是一个基于 redux 和 redux-saga 的数据流方案.前端

为何使用dva

由于它简化了react引入redux的过程。java

传统redux与dva对比

redux:react

clipboard.png

开发时,咱们须要action,reducer等文件,而且须要自行分类,不太清晰。webpack

dva:web

clipboard.png

开发时,把 store 及 saga 统一为一个 model 的概念, 写在一个 js 文件里面,分类清晰。
增长了一个 Subscriptions, 用于收集其余来源的 action。redux

如何使用dva

函数式组件与非函数式组件

概要

HelloWorldModel.js服务器

export default {
  namespace: 'HelloWorldModel',
  state: {str:"hi"},
  reducers: {
    
  },
};

这是react组件的建立:react-router

class HelloWorld extends Component {
  constructor() {
    super()
    this.state = {  }
  }

  sayHi () {
    alert('this.props.HelloWorldModel.str)
  }

  render () {
    return (
      <div onClick={this.sayHi.bind(this)}>Hello World</div>
    )
  }
}

export default connect(({ HelloWorldModel }) => ({
  HelloWorldModel,
}))(HelloWorld);

函数式组件app

const HelloWorld = (props) => {
  const sayHi = (event) => alert(this.props.HelloWorldModel.str)
  return (
    <div onClick={sayHi}>Hello World</div>
  )
}
export default connect(({ HelloWorldModel }) => ({
  HelloWorldModel,
}))(HelloWorld);

属性与状态

页面的数据分为2大类:
1.页面属性:Modal打开或者关闭,与用户行为相关,与后台数据无关
2.页面状态:Table展现的数据内容,与用户行为无关,与后台数据相关
我一般在react组件中直接使用state做为页面属性,将页面状态存在model中,
而函数式组件,则将页面属性和状态所有存放在model中。dom

生命周期

上面是react组件和函数式组件的写法区别,
经过react组件写法声明的组件继承了“react.Component”的一些属性及方法,如生命周期钩子函数等。
而函数式组件只是个返回dom节点的方法,因此不具有生命周期函数。
由于dva的数据流是单向的,
用户行为=》视图=》model.Effect=>model.Reducer=>store变化=>视图更新,
react组件能够在“componentWillReceiveProps”钩子中决定是否容许当前组件内的数据流动,
函数式组件只能被动接收数据流动。

页面与状态的绑定和流转

如上述代码,页面与model的绑定,是经过connect方法实现的,在connect方法中,入参能够抓取到全部导入的model文件,咱们能够在每一个组件中(须要关联model的)“重载”connect方法,只获取咱们当前页面所需的model,展现在页面上。而页面的事件则可使用dispatch触发model的Effect事件与服务端交互以后执行reducer,store(model数据)变化后,页面由于connect了model,至关于订阅了model的变化,数据流入,页面更新。

公共状态抽离

一些公用的状态是能够抽离到同一个model中的,如登陆态,上一次查询参数等。

实际应用中的一些解决方案

动态组件

dva提供dynamic方法支持动态加载组件和model,

import dynamic from 'dva/dynamic';

const UserPageComponent = dynamic({
  app,
  models: () => [
    import('./models/users'),
  ],
  component: () => import('./routes/UserPage'),
});

经过动态加载后,build出来的文件将index.js切割成index.js(体积变小) + 1.async.js等等,
可是index.js默认是经过"./"来加载1.async.js的,对于前端静态资源与服务端应用不在同一台服务器的状况,如
java boot应用 发布在http://xxx.com/a =》 a.ftl 中引用 dva build以后的静态资源,而静态资源发布倒是在另外一台服务器上http://zzz.com/dvaBuild/dist,
index.js仍是去访问默认的"./1.async.js" 其实访问的是http://xxx.com/a/1.async.js,...
能够直接在页面script标签中,

window.__webpack_public_path__ = 'http://zzz.com/dvaBuild/dist';

路由跳转

权限判断(接入第三方登录)

1.是否登录
在GlobalModel中保存着登陆态,路由中使用AuthComponent替换Route,在渲染路由组件的时候就会判断是否登录,若是没有登录渲染正在登录loading页面,等待第三方登录接口判断已经登录,页面会自动更新为路由组件。
这是第三方登录,若是是内部登录使用react-router跳转。
AuthComponent

@connect(({GlobalModel}) => GlobalModel)
export default class AuthComponent extends PureComponent {
  render() {
    const { component: Component, isLogin, ...rest } = this.props;
    return  (
      <Route
      {...rest}
      render={props =>
        isLogin == 1 ? (
          <Component {...props}/>
        ) : (
          <Logining></Logining>
        )
      }
    />
    )
  }
}

GlobalModel

effects: {
    *CheckLogin({payload,callback}, {call,select,put}) {
        const loginfoResult = yield call(getLoginInfo);
        if(loginfoResult && loginfoResult.ResponseStatus && loginfoResult.ResponseStatus.Ack == "Success" && loginfoResult.userBasicInfoDTO){
          if(loginfoResult.userBasicInfoDTO && loginfoResult.userBasicInfoDTO.userAccount && checkPermission(loginfoResult.userBasicInfoDTO.userAccount)){
            yield put({type:"save",loginInfo:loginfoResult})
            callback();
          }else{
            yield put( routerRedux.push('/NoPermission') ); //没有权限
          }
        }else{
          window.location.href = getLoginUrl();
        }
    },

须要在各个路由页面绑定的model的路由切换订阅方法中作登录判断,
页面切换就要判断是否登录或鉴权

subscriptions: {
    setup({ dispatch, history }) {  // eslint-disable-line
      return history.listen((location) => {
        dispatch({
          type: "GlobalModel/onShow",
          callback: () => {

                dispatch({type:"BaseInfoQuery",payload:{}});
            }

            })
      })

    },
相关文章
相关标签/搜索