antd pro项目主要分为services、models、components层三层结构,调用接口时也需要相互配合。
antd pro的底层基础框架使用的是dva,dva采用effect的方式来管理同步化异步
在dva中主要分为3层 services models components
models层用于存放数据以及对数据进行操作,services层调用请求后台接口的方法,components层用于书写页面逻辑代码
services层
import request from '@/utils/request';
export async function doit(payload) {
const {id} = payload;
let url = `/api/v2/.../${id}`;
return request(url,{
mode: 'cors',
method: 'GET',
})
.then(res => {
return res;
})
.catch(err => console.log(err));
}
models层中的effects是与后台交互、处理数据逻辑的地方
import {doit} from '../../'
export default {
namespace: 'test',
effects: {
*fetchNum ({payload,callback},{call,put}) {
const res = yield call (doit,payload)
//doit是引入services层那个js文件的doit方法,payload是后台要求传递的参数,res就是后台返过来的数据
yield put ({
type: 'addNum', //这就是reducer的addNum方法,put用来出发reducer中的方法,payload是传过去的参数。同时也能触发同等级effects中的方法
payload: {
num: res.data //把后台返回的数据赋值给num,假如哪个reducer中的方法是由这里effects去触发的,哪个num名必须是这里的名字num,如果reducer中的方法不是这触发,那名字可以随意取
}
})
}
}
reducers: {
addNum (state,{payload:{num}}) {
return {...state,num}
}
}
}
components层
页面如果需要使用models层的数据,要用connect进行连接,即在页面在引入import {connect} from 'dva';@connect(state => ({test:state.test})) 通过this.props获取数据
this.props.dispatch({
type: 'test/fetchNum', test对应models层的命名空间namespace
payload: {
numCount: ++1
}
})
使用mock数据主要包括以下几步:
1、添加mock接口
2、添加service文件
3、添加model(需引入service函数)
4、页面链接model
5、页面调用model中的effect函数
6、model中的effects通过reducer中的函数将数据返回到页面
7、页面通过this.props获取数据
具体操作就是在项目根目录下,mock文件夹中新建record.js文件,用于存放mock数据
export default {
'GET /love/record':{
message: 'Succeed',
code:0,
data: [
{
key: '1',
Name: '违规操作',
age: '口腔科',
address: '人民医院',
tags: '2019-03-21 12:56:12',
questions: '温度'
},
{
key: '2',
Name: '违规操作',
age: '皮肤科',
address: '人民医院',
tags: '2019-03-21 12:56:12',
questions: '压力'
},
]
}
}
然后在src目录下的services文件夹中新建一个record.js文件,用来创建请求数据的函数,框架已经为我们封装好了request函数(可能需要我们对request.js文件进行补充),我们可以直接进行使用
import request from '../utils/request' ;
export async function getRecord (payload) {
return request('/love/record',{
//如果路径中有参数,需要用字符串模板进行拼接``
method: 'GET'
})
.then(res => {
return res;
}
.catch(err => console.log(err))
}
src目录下的models文件夹是store文件夹,用来定义state
新建record.js文件
引入我们在services文件夹中创建的请求数据的函数
import { getRecord } from '../services/record' ;
export default {
namespace: 'demo',
state:{
record: [],
},
effects: {
*getRecord(payload,{call,put}) {
const res = yield call(getRecord,payload)
yield put({
type: 'updateToView',
payload:{record:res.data}
});
}
},
reducers: {
updateToView(state, { payload }) {
return {
...state,
...payload,
}
}
}
}
最后在page页面中,通过this.props就可以得到我们想要的数据
import { connect } from 'dva' ;
@connect(state=> ({
demo:state.demo
})
componentDidMount(){
const { dispatch } = this.props;
dispatch({
//需要调用对于namespace下effects中的该函数
type: 'record/getRecord',
})
}
console.log(this.props)就可以得到结果
const { demo } = this.props
我的request.js文件
import fetch from 'dva/fetch';
import { message } from 'antd';
import { error } from '@/utils/error';
const checkStatus = response => {
if (response.status >= 200 && response.status < 300) {
return response;
}
const errortext = error[response.status] || response.statusText;
let isLogin = response.url.search('/unsecure/login') != -1;
if (response.status === 401) {
if (isLogin) {
message.error(`请求错误 ${response.status}: ${errortext}`);
} else {
console.log('gogogo')
router.push('/user/login');
}
} else {
if (!isLogin) {
message.error(`请求错误 ${response.status}: ${errortext}`);
}
}
return response;
};
export default function request(url, option) {
//获取token
let token = localStorage.getItem('token');
const options = {
...option,
headers: {
'X-Authorization': token,
'x-language': 'chinese',
},
};
const newOptions = { ...options, credentials: 'include' };
if (
newOptions.method === 'POST' ||
newOptions.method === 'PUT' ||
newOptions.method === 'DELETE'
) {
if (!(newOptions.body instanceof FormData)) {
newOptions.headers = {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
...newOptions.headers,
};
if (newOptions.dataType != 'string') {
newOptions.body = JSON.stringify(newOptions.body);
}
} else {
newOptions.headers = {
Accept: 'application/json',
...newOptions.headers,
};
}
}
return (
fetch(url, newOptions)
.then(checkStatus)
.then(response => {
if (newOptions.responseType === 'blob') {
return response.blob();
}
let type = typeof response;
switch (type) {
case 'object':
return response.json();
case 'string':
return response.text();
}
return response.json();
})
.then(res => {
return res;
})
.catch(e => { })
);
}
error.js文件
export default {
40101: '再输错两次将锁住',
40200: '用户不存在',
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户权限错误。',
403: '权限信息错误。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维保。',
504: '网关超时。',
}