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: '网关超时。',
}