代码重构
让代码放在更适合它的位置,使得项目更容易实现代码复用,也更加容易维护。
我们现在的代码 ./src/models/hero.js
*fetch({ type, payload }, { put, call, select }) {
const data = yield request('/api/herodetails.json', { ---step1
method: 'POST',
headers: { ---step2
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify({ ---step3
ename: 110,
}),
});
const localData = [ ---step4
{
ename: 105,
cname: '廉颇',
title: '正义爆轰',
new_type: 0,
hero_type: 3,
skin_name: '正义爆轰|地狱岩魂',
},
{
ename: 106,
cname: '小乔',
title: '恋之微风',
new_type: 0,
hero_type: 2,
skin_name: '恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽',
},
];
yield put({
type: 'save',
payload: {
heros: data || localData,
},
});
},
- step1 将接口地址散乱地写在models代码中,不便于维护,也不便于接口变动
- step2 请求设置的headers,应该是通用的,除了特殊接口需要单独设定请求头,其他的应该都是一样的
- step3 所有的post请求的body,都要进行JSON.stringify
- step4 静态数据,已经放在mock中了,这里不再需要
请求相关的都放到./src/utils/request.js
```diff export default function request(url, options) {
- if(options.method === ‘POST’){
- options.headers = {
- Accept: ‘application/json’,
- ‘Content-Type’: ‘application/json; charset=utf-8’,
- …options.headers,
- }
- options.body = JSON.stringify(options.body);
- }
return fetch(url, options).then(response => {
const resData = response.json();
return resData;
}).catch(e=>{
console.log(e)
});
}
```
我们又对这个文件进行了优化,但要用到实际生产中,它还远远不够。我们会在后续的教程中不断地完善和丰富它。所以如果,你现在就要将它用于生产环境,建议你拷贝ant-design-pro 的request文件。
接口相关的都放到./src/services/hero.js
```javascript import request from ‘../utils/request’;
export async function queryHeroList() { return request(‘/api/herolist.json’); } export async function getHeroDetails(params) { return request(‘/api/herodetails.json’, { method: ‘POST’, body: params, }); }
## ./src/models/hero.js
```javascript
- import request from '../utils/request';
+ import { queryHeroList, getHeroDetails } from '../services/hero';
...
*fetch({ type, payload }, { put, call, select }) {
const herolist = yield call(queryHeroList);
const herodetails = yield call(getHeroDetails, { ename: 110 });
console.log(herodetails);
yield put({
type: 'save',
payload: {
heros: herolist,
},
});
},
这样models就变得很干净了,也很好理解,这里的yield call是指等待调用某个函数执行完毕。 到这里我们已经写了一些比较良好的代码,来实现了英雄页面的数据初始化。
接口统一管理
现在我们参考之前的步骤,来取得局内布局的初始化数据。
我们会同步增加 ./mock/item.js
和 ./services/item.js
文件,把文件细粒化确实便于项目的管理,但是我们总共就那么几个接口,这么做就没什么必要。所以我们修改文件名 ./mock/hero.js
==> ./mock/api.js
, ./services/hero.js
==> ./services/api.js
这样子其他页面的接口,就可以统一管理了。
./mock/api.js
import herolist from './herolist.json';
import item from './item.json';
import summoner from './summoner.json';
import ming from './ming.json';
export default {
'/api/herolist.json': herolist,
'POST /api/herodetails.json': (req, res) => {
const { ename } = req.body;
const hero = herolist.filter(item => item.ename === parseInt(ename, 10))[0];
res.send(hero);
},
'/api/item.json': item,
'/api/summoner.json': summoner,
'/api/ming.json': ming,
};
./services/api.js
import request from '../utils/request';
export async function queryHeroList() {
return request('/api/herolist.json');
}
export async function getHeroDetails(params) {
return request('/api/herodetails.json', {
method: 'POST',
body: params,
});
}
export async function queryItem() {
return request('/api/item.json');
}
export async function querySummoner() {
return request('/api/summoner.json');
}
export async function queryMing() {
return request('/api/ming.json');
}
现在感觉是不是比较工整和规范啦,你可以在获得接口文档之后优先编写这两个文件,这样就实现了一个前端数据服务,后续你自己或者其他协作成员,可以直接发起http请求,而不再理会数据模拟。
代码回顾:这节课的全部代码