官网上介绍:dva 是基于redux,redux-saga和react-router的轻量级前端框架。也就是 dva 主要是基于 redux 和 redux-saga 的数据流解决方案,内置了 react-router 和 fetch。javascript
dva 是 antd design pro 基于 React 的中后台管理控制台的脚手架选择的数据流管理框架,作 antd-pro 搭建的项目的时候开始接触到这个框架,在脚手架造成的目录中:dva 分别在 '/src/models' 中管理全局数据,在 '/pages/肯定的某一页面/models' 中管理某一页面的数据。html
下面代码是在 antd-pro 脚手架搭建起来的项目中的实践,原理部分的掌握还欠缺,先记下来经常使用的用法,和基础知识。前端
// connect 也是链接的数据是对 store 中的数据的浅复制,当是引用类型的数据的时候,若是直接修改 props 中映射数据, store 里面的数据也会被修改
@connect(state => ({
detailsTable: state['event/addNewCard'],// 这里传入的 state 参数是一个“彻底体”,包含了全部 namespace 下的 state,以 namespace 为 key 值进行区分
loading: state.loading,
layout: state.layout,
}))
export default class PuzzleCardsPage extends Component {
addNewCard(){
dispatch({
type:'event/addNewCard',
payload:{},//传递数据的载体
//还能够传进去一个回调函数,处理当数据没有正确请求的时候的处理逻辑
callback: res => {
message.error(res)
}
})
}
render() {
return (
<div> <Button onClick={this.addNewCard}> 添加卡片 </Button> </div>
);
}
}
复制代码
export default {
namespace: '',//不一样的页面或操做对应不一样的命名空间
state:{},
effects:{//至关于 redux 的 middleware,为了保证 reducer 的纯粹性,有一些须要对数据在进行处理的操做放在 effects 里面,好比在 effects 里面能够调用 services 方法进行异步请求。
*addByONe({payload, error}, { call, put, select }) { // 传入这个 Generator 函数的有两个参数,一个是匹配这个 effects 的 action 对象,所以能够取到 payload 和 error 字段。 另外一个是 effect 原语集,call 主要处理异步逻辑(好比发起请求)它第一个参数是一个函数,要求函数返回 Promise,以后的参数是该函数调用时的入参。
const num = yield select(state => state.num) // effects 里面主要经过yield select 获取 state
let param1;
param1 = num + param;
yield put({//effects 里面经过 put 方法触发 action,和 pages 中的dispatch 方法如出一辙,能够继续请求其余 namespace 中的 effects 或者 reducer ,不一样的是,请求自身的 effects 或者 reducer 时不须要指定 namespace 名称
type: 'save',
num:param1
});
}
},
//用来保存更新 state 值 上面的 put 方法调用这里的方法,当不须要发起请求,只修改state中数据的方法放在这里,且这里的方法也可以被外部调用
reducers: {
save(state, action) { //state 是当前命名空间的 state,这里的 action 包含了上面传递的参数和 type
return { ...state, ...action.num };
},
},
}
复制代码
model 中几个基本属性,其中 namespace 和 state 是一个 model 中最基本的两个成员。java
namespace
:model 的命名空间,只能用字符串,是一个 model 的惟一标识。一个大型应用可能包含多个 model,经过 namespace 区分。state
:当前 model 状态的初始值,表示当前状态。是该 model 管理的数据reducers
:用于处理同步操做,更新修改 state,由 action 触发。reducer 是一个纯函数,它接受当前的 state 及一个 action 对象。action 对象里面能够包含数据体(payload)做为入参,须要返回一个新的 state。effects
:用于处理异步操做(例如:与服务端交互)和复杂的数据处理逻辑,也是由 action 触发。可是,它不能够修改 state,要经过触发 action 调用 reducer 实现对 state 的间接操做。action
:是 reducers 及 effects 的触发器,通常是一个对象,形如{ type: 'add', payload: todo },经过 type 属性能够匹配到具体某个 reducer 或者 effect,payload 属性则是数据体,用于传送给 reducer 或 effect。dva-loading
插件,可是使用脚手架搭建项目,直接在页面中使用就能够了,经过 connect 方法将加载的状态传递到组件中,下面是几种具体的方法:(1)loading.effects['chart/fetch']
监听这个方法是否执行完毕,若执行完毕。loading 的值就变为 false。react
@connect(({ chart, loading }) => ({
chart,
loading: loading.effects['chart/fetch'],
}))
复制代码
(2)loading.models.monitor
监听这个模块是否执行完毕,注意这里的 [monitor] 是命名空间。监听的是当前页面用到的命名空间里面的方法。若执行完毕,loading 的状态变为 false。git
@connect(({ monitor, loading }) => ({
monitor,
loading: loading.models.monitor,
}))
复制代码
(3)还有一种用法是 loading.global,经过全局的状态控制 loading 的状态。loading.global
监听这个页面的加载状态。当页面处于异步加载状态时该值为 true,当页面加载完成时,自动监听该值为 false。github
这里是绑定到 dva 的自动控制 loading 数据的插件。再也不须要重复写 showLoading 和 hideLoading。redux
文档中讲的很清楚,并且在掌握上面的基础知识后,也不难上手使用这个框架。前端框架
// 建立应用
const app = dva();
// 注册 Model
app.model({
namespace: 'count',
state: 0,
reducers: {
add(state) { return state + 1 },
},
effects: {
*addAfter1Second(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'add' });
},
},
});
// 注册视图
app.router(() => <ConnectedApp />);
// 启动应用,将组件挂载到 id 为 root 的元素上
app.start('#root');
复制代码