代码重构

让代码放在更适合它的位置,使得项目更容易实现代码复用,也更加容易维护。 我们现在的代码 ./src/models/hero.js

  1. *fetch({ type, payload }, { put, call, select }) {
  2. const data = yield request('/api/herodetails.json', { ---step1
  3. method: 'POST',
  4. headers: { ---step2
  5. Accept: 'application/json',
  6. 'Content-Type': 'application/json; charset=utf-8',
  7. },
  8. body: JSON.stringify({ ---step3
  9. ename: 110,
  10. }),
  11. });
  12. const localData = [ ---step4
  13. {
  14. ename: 105,
  15. cname: '廉颇',
  16. title: '正义爆轰',
  17. new_type: 0,
  18. hero_type: 3,
  19. skin_name: '正义爆轰|地狱岩魂',
  20. },
  21. {
  22. ename: 106,
  23. cname: '小乔',
  24. title: '恋之微风',
  25. new_type: 0,
  26. hero_type: 2,
  27. skin_name: '恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽',
  28. },
  29. ];
  30. yield put({
  31. type: 'save',
  32. payload: {
  33. heros: data || localData,
  34. },
  35. });
  36. },
  • 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, }); }

  1. ## ./src/models/hero.js
  2. ```javascript
  3. - import request from '../utils/request';
  4. + import { queryHeroList, getHeroDetails } from '../services/hero';
  5. ...
  6. *fetch({ type, payload }, { put, call, select }) {
  7. const herolist = yield call(queryHeroList);
  8. const herodetails = yield call(getHeroDetails, { ename: 110 });
  9. console.log(herodetails);
  10. yield put({
  11. type: 'save',
  12. payload: {
  13. heros: herolist,
  14. },
  15. });
  16. },

这样models就变得很干净了,也很好理解,这里的yield call是指等待调用某个函数执行完毕。 到这里我们已经写了一些比较良好的代码,来实现了英雄页面的数据初始化。

接口统一管理

现在我们参考之前的步骤,来取得局内布局的初始化数据。 我们会同步增加 ./mock/item.js./services/item.js 文件,把文件细粒化确实便于项目的管理,但是我们总共就那么几个接口,这么做就没什么必要。所以我们修改文件名 ./mock/hero.js ==> ./mock/api.js , ./services/hero.js ==> ./services/api.js 这样子其他页面的接口,就可以统一管理了。

./mock/api.js

  1. import herolist from './herolist.json';
  2. import item from './item.json';
  3. import summoner from './summoner.json';
  4. import ming from './ming.json';
  5. export default {
  6. '/api/herolist.json': herolist,
  7. 'POST /api/herodetails.json': (req, res) => {
  8. const { ename } = req.body;
  9. const hero = herolist.filter(item => item.ename === parseInt(ename, 10))[0];
  10. res.send(hero);
  11. },
  12. '/api/item.json': item,
  13. '/api/summoner.json': summoner,
  14. '/api/ming.json': ming,
  15. };

./services/api.js

  1. import request from '../utils/request';
  2. export async function queryHeroList() {
  3. return request('/api/herolist.json');
  4. }
  5. export async function getHeroDetails(params) {
  6. return request('/api/herodetails.json', {
  7. method: 'POST',
  8. body: params,
  9. });
  10. }
  11. export async function queryItem() {
  12. return request('/api/item.json');
  13. }
  14. export async function querySummoner() {
  15. return request('/api/summoner.json');
  16. }
  17. export async function queryMing() {
  18. return request('/api/ming.json');
  19. }

现在感觉是不是比较工整和规范啦,你可以在获得接口文档之后优先编写这两个文件,这样就实现了一个前端数据服务,后续你自己或者其他协作成员,可以直接发起http请求,而不再理会数据模拟。

代码回顾:这节课的全部代码