一、dva 介绍

dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。dva = React-Router + Redux + Redux-saga

二、dva 概念

数据流向:
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变State,所以在dva中,数据流向非常清晰简明,参考下面的图

dva入门_es6

三、Models

通过 dva()可以产生一个app实例,该app实例上有这么几个重要的api
## 1. State
初始化数据的,可以是任意的值,类似于vuex中的state模块/redux中reducers模块中的initState
## 2. Action
action就是一个普通的js对象,它是改变 State 的唯一途径。action 必须带有 type 属性指明具体的行为,其它字段可以自定义,类似 于redux中的action
## 3. Dispatch
dispatching function 是一个用于触发 action 的函数
## 4. Reducer
相当于redux中的reducer,根据之前的状态和action生成最新的状态
## 5. Effect
用于异步操作,底层是使用了redux-saga
## 6. Subscription
用于订阅一个数据源,然后根据条件 dispatch 需要的 action
## 7. namespace
model的命名空间,同时也是他在全局 state 上的属性,只能用字符串,不支持通过 . 的方式创建多层命名空间

四、Router

dva 实例提供了 router 方法来控制路由,使用的是react-router
在 dva 中,通常需要 connect Model的组件都是 Route Components(路由组件),组织在/routes/目录下,而/components/目录下则是纯组件(非路由组件)

五、相关 Api

dynamic:
解决组件动态加载问题的 util 方法
使用:
import dynamic from 'dva/dynamic';

const UserPageComponent = dynamic({
app,
models: () => [
import('./models/users'),
],
component: () => import('./routes/UserPage'),
});
## app: dva 实例,加载 models 时需要
## models: 返回 Promise 数组的函数,Promise 返回 dva model
## component:返回 Promise 的函数,Promise 返回 React Component
生命周期钩子:
1.onError(捕获错误)
2.onAction(action被dispatch触发)
3.onStateChange(state改变时触发,可用于同步 state 到 localStorage,服务器端)
4.onReducer(封装reducer执行)
5.onEffect(封装effect执行)
6.onHmr(模块热替换相关)
7.extraReducers(指定额外的 reducer)
8.extraEnhancers(指定额外的StoreEnhancer)
app实例上的api
1.app.model(model) // 注册model
2.app.unmodel(namespace) // 取消model注册,清理 reducers, effects 和 subscriptions。subscription 如果没有返回 unlisten 函数,使用 app.unmodel 会给予警告
3.app.replaceModel(model) // 替换model为新model,只在app.start()之后可用.会保留旧的state状态
4.app.router((router) => routerConfig) // 注册路由表
5.app.start(selector) // 启动应用