dva开发模式分为 services(服务层)、models(数据层)、和 routes(组件层) 三个板块。
services层:负责提供接口请求,诸如:数据的查询、删除、修改、添加等等操作需要的接口。
models层:负责对处理数据和逻辑。
routes层:提供具体的组件(负责浏览器页面显示)

services
代码示例:
export async function getUserList(params) {
return fetch('/users', { // dva通过fetch发送请求
method: 'GET', // method设置请求方式(GET、POST、PUT、DELETE)(根据请求方式的不同可以自行添加请求头)
mode: 'cors', // 避免cors攻击
credentials: 'include'
}).then(function (response) {
//格式化json数据并返回
response.json().then(function (data) {
return data; // 返回响应数据
});
}).catch(function (e) {
console.log("Oops, error");
});
}
async表示此方法是异步方法,此方法返回一个promise对象。
models
models层可以分为三个板块:
(1)namespace:model的名字,用在routes页面组件当中,使页面找到相应的model。可以理解为【命名空间】,用于解决多个model之间的干扰问题。
namespace: 'userInfo'
(2)state:model中存放数据的地方。
state是整个应用的数据层,应用的 state 被存储在一个 object tree 中,应用的初始state在model中定义,由 model state 组成全局的 state。操作时要当成不可变数据(immutable data)来对待,保证每次都是全新的对象,没有引用关系。
state = {
userInfo: [],
detailUser: {},
},
(3)subscriptions:监听器。可以监听路由、鼠标、键盘、服务器连接、状态等发生的变化,根据这些变化可以做出相应的处理。位于其中的方法名称可以随便定义,当进入监听页面时会触发,且只在当前页面触发一次。
Subscriptions是一种从源获取数据的方法,它来自于elm。
Subscription 语义是订阅,用于订阅一个数据源,然后根据条件dispatch需要的action。
数据源可以是当前的时间、服务器的websocket连接、keyboard输入、geolocation变化、history路由变化等等。
subscriptions: {
setup({ dispatch, history }) {
history.listen((location) => {
//当进入这个页面的时候,就会调用下面的dispatch方法。
if (location.pathname === '/userInfo') {
dispatch({
type: 'update',
payload: {
id: 'A001',
userName: 'update'
},
})
}
})
},
},
(4)effects:Action处理器,用于处理异步动作(effect 是一个Generator 函数)
用于处理异步操作和业务逻辑,不直接修改 state,简单的来说,就是获取从服务端获取数据,并且发起一个 action 交给 reducer 。
effects: {
// 查询所有的用户数据
*searchAllUsers({ payload }, { call, put }) {
const res = yield call(searchAllUsers, payload);
const detailUser = yield select(state => state.detailUser);
if (res) {
yield put({
type: 'updateState',
payload: {
allUsers: res.allUsers,
},
});
}
return res;
},
示例代码分析:
action:是一个普通的JavaScript对象,是改变state的唯一途径,通过dispatch函数调用一个caction,从而改变对应的数据。
action格式:一个
type,表示这个action要触发什么操作;payload则表示这个action将要传递的数据
{
type: 'updateState',
payload: {
detailData: list,
},
}
* query(action, {call, put, select}){}:effect是一个 Generator 函数,每个函数以*开头。
call:调用异步逻辑,执行异步函数(即我们在services层定义的接口方法),支持Promise。call有两个参数,第一个参数是要调用的services层的函数,第二个参数是需要传递的参数。
put:发出一个action,类似于dispatch。
yield:表示【同步调用】,在effects内,Generator函数通过yield把异步操作同步化。无论是yield 亦或是 async 目的只有一个: 让异步编写跟同步一样 ,从而能够很好的控制执行流程。
select:用于获取state中的数据。
(5)reducers:Action处理器,用于处理同步操作。可以看做是state 的计算器。它的作用是根据Action,从上一个State 算出当前State。
以key/value 格式定义 reducer,用于处理同步操作,唯一可以修改 state 的地方。由 action 触发。其实一个纯函数。
注意:reducers是唯一一个可以更新state的地方
reducers: {
updateState(state, action) {
return {
...state,
...action.payload,
};
},
},
routes
(1)连接 models 和 routes :
@connect(({ dimension, loading }) => ({
dimension,
fetchListLoading: loading.effects['dimension/fetchDimensionList'],
}))
以上代码分析:@ 是es7的 装饰器 ,connect 用于连接 model 和 router,dimension 是 model 的 namespace ,代表着一个 model ,通过这样的方式,把该 model 加到 props 当中,通过
const { dimension } = this.props;
就可以访问 model 中的 state 属性了。
(2)通过
const { dispatch } = this.props;
通过 dispatch 发出 action ,调用 model 中的 effects 或 reducers 内的 方法,例如:
const { dispatch } = this.props;
dispatch({
type: "bank/queryList",
payload: { ...dateList, ...params },
});