Vue+Ant Design Vue+Mockjs----mock篇

江枫思渺然 提交于 2019-12-11 01:19:56

Mock

mock 介绍

mockjs官方使用文档

目的

方便生成随机数据,拦截Ajax请求。

  偶尔会写一些前端的项目,参考一些比较知名的UI框架,里面很多例子都会把数据直接写在里面,作为参考,因此很多项目里面也会这样手写数据,直接写死在前端,将代码与mock数据紧密结合在一起,每次需要修改数据,都需要直接改动到代码层,前端本身改动就非常大,如此频繁的修改代码层面显然不是很好的实践。

同时手写的数据,美观与真实性差异就看作者水平了。

优点
  • 非常简单强大,入手快
  • 拦截api请求,mock出真实的前后端交互情况
  • 更改mock数据方便,与业务代码分离,频繁修改也不会有太大的危险
  • 在后端接口准备好前,通过mock接口来模拟与后台的交互,同时调整数据结构。
  • 开发过程中,mock数据也可以与后端提前讨论,引导后台的数据结构更加合理。
  • 后台开发完以后,可以一次性切换接口
缺点
  • 灵活性不够,无法mock后台一些异常处理返回
  • Build成静态文件以后线上无法使用(或许我没有找对方法)
comment

   针对第一个问题,忽然想到一种方案,或许你可以在同一个接口里面,mock不同的response,然后采用随机函数,随机的返回各种异常response,这样可以测试前端应对各种后台error作出的处理是否符合预期。

安装

cd myProject

#仅安装到本地开发环境
npm install mockjs --save-dev  

mock 实现

src
│       
└───api  //api文件夹,所有的接口都到单独抽出来,放在该目录下
│       index.js  //入口函数,对外暴露
│       search.js  //为每一类接口单独创建的文件,一类接口统一放在一个目录下
│
└───mock
        index.js   //所有的mock  api都会写在下面,如果需要,也可以拆分

mock/index.js

/**
 * data mock refer to http://mockjs.com
 *
 */
const Mock = require('mockjs');
const util = require('./util');

module.exports = function (app) {

  app.get('/mock/v1/search', function (rep, res) {
     let result = {
      "data|24": [{
        "date": "@date('yyyy-MM-dd')",
        "logNum": "@natural(60, 1000)"
      }
      ]
    };
    //util.wrapResultSuccess  包装了response返回,规范统一
    res.send(util.wrapResultSuccess(Mock.mock(result).data));
  });


}

vue.config.js

//vue cli3 配置文件
  devServer: {
    port: port,
    open: true,
    host: '127.0.0.1',
    https: false,
    hotOnly: false,
    overlay: {
      warnings: false,
      errors: true
    },
  #根据当前环境,把整个mock目录加载到项目中,每次修改mock文件需要重启
    before: process.env.ENV == 'mock' ? require('./src/mock'):null,
  },

api/index.js

/**
 * api interface
 */

import search from '@/api/search'

export default {
  search
}

api/search.js

/**
 * article模块接口列表
 */

import axios from '@/plugins/request';
import trend from "@/plugins/handle"


const search = {

  statusPing () {
    return axios.get(`/status_ping`);
  },

  //search
  search (body) {
    return axios.get(`v1/search`, body);
  },


export default search;


utils/request.js

把axiso做了一层封装,每一次前端请求都会把x-request-id带给后台,后台打印日志的时候,都会打印这个id,方便日后追踪问题,同事针对一些后台的error,可以做一些统一的处理。


import router from '@/pages/login/router';

const xss = require("xss");

let instance = axios.create({
  timeout: 1000 * 60
    });

instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

function getRandomTraceId() {
  let characters = 'abcdefghijklmnopqrstuvwxyz1234567890';
  let result = '';
  let idLength = 32;

  try {
    for (let index = 0; index < idLength; index++) {
      result += characters[parseInt(Math.random() * characters.length, 10)];
    }
  } catch (error) {
    result = 'getRandomTraceIdError';
  }

  return result;
}
/**
 * request interceptor
 * Before each request, if token exists, carry it in the request header
 */
instance.interceptors.request.use(
    config => {
      // console.log(JSON.stringify(config));

      //add trace id for request
      config.headers['x-request-id'] = getRandomTraceId();

      //xss filter request url
      config.url = xss(config.url);


      // 登录流程控制中,根据本地是否存在token判断用户的登录情况
      // 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
      // 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码
      // 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。
      // const token = store.state.token;
      // token && (config.headers.Authorization = token);
      return config;
    },
    error => Promise.error(error))


instance.interceptors.response.use(

    res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),

    error => {
      const {response} = error;
      if (response) {
        errorHandle(response.status, response.data.message);
        return Promise.reject(response);
      } else {
        // 处理断网的情况
        // eg:请求超时或断网时,更新state的network状态
        // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
        // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
        if (!window.navigator.onLine) {
          // store.commit('changeNetwork', false);
        } else {
          return Promise.reject(error);
        }
      }
    });

export default instance;

main.js

直接把api类挂载到vue上,这样方便使用,也可以直接到使用类里面去引入

import api from '@/api'

Vue.prototype.$api = api;

window.APP=new Vue({
  router,
  i18n,
  api,
  store,
  render: h => h(App)
}).$mount('#app')

how to use

async getData(){
     let response = await this.$api.search.search(request);
       if (response.status == 200 && response.data.data) {
       console.log(`response.data.data = &{response.data.data}`);
       }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!