Skip to content

手把手撸后台-Vue3_Webpack_mock

安装

bash

npm install mockjs -D

npm install axios -S

main.js

在 main.js 中引入 mock

js
import { mockXHR } from "./mock/index";

mockXHR();

使用

index.js

在 src 目录下新建 mock 文件夹,在 mock 文件夹下新建 index.js

js
const Mock = require("mockjs");
const { param2Obj } = require("./utils");

const login = require("./login");

const mocks = [...login];

// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
function mockXHR() {
  // mock patch
  // https://github.com/nuysoft/Mock/issues/300
  Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send;
  Mock.XHR.prototype.send = function () {
    if (this.custom.xhr) {
      this.custom.xhr.withCredentials = this.withCredentials || false;

      if (this.responseType) {
        this.custom.xhr.responseType = this.responseType;
      }
    }
    this.proxy_send(...arguments);
  };

  function XHR2ExpressReqWrap(respond) {
    return function (options) {
      let result = null;
      if (respond instanceof Function) {
        const { body, type, url } = options;
        // https://expressjs.com/en/4x/api.html#req
        result = respond({
          method: type,
          body: JSON.parse(body),
          query: param2Obj(url),
        });
      } else {
        result = respond;
      }
      return Mock.mock(result);
    };
  }

  for (const i of mocks) {
    Mock.mock(
      new RegExp(i.url),
      i.type || "get",
      XHR2ExpressReqWrap(i.response)
    );
  }
}

module.exports = {
  mocks,
  mockXHR,
};

utils.js 文件

  • 在 mock 文件夹下新建 utils.js 文件,用于存放一些公共方法
js
/**
 * @param {string} url
 * @returns {Object}
 */
function param2Obj(url) {
  const search = decodeURIComponent(url.split("?")[1]).replace(/\+/g, " ");
  if (!search) {
    return {};
  }
  const obj = {};
  const searchArr = search.split("&");
  searchArr.forEach((v) => {
    const index = v.indexOf("=");
    if (index !== -1) {
      const name = v.substring(0, index);
      const val = v.substring(index + 1, v.length);
      obj[name] = val;
    }
  });
  return obj;
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
function deepClone(source) {
  if (!source && typeof source !== "object") {
    throw new Error("error arguments", "deepClone");
  }
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach((keys) => {
    if (source[keys] && typeof source[keys] === "object") {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}

module.exports = {
  param2Obj,
  deepClone,
};

在 mock 文件夹下新建 login 文件夹

下面新建 index.js,模拟接口

bash
post 对应的就是 body。 get 对应的就是 query
js
module.exports = [
  // user login
  {
    url: "/api/loginpost",
    type: "post",
    response: (config) => {
      console.log(config);
      const { username, password } = config.body;
      console.log(username);
      console.log(password);
      // mock error
      return {
        code: 200,
        message: "测试post接口",
      };
    },
  },
  {
    url: "/api/loginget",
    type: "get",
    response: (config) => {
      console.log(config);
      const { username, password } = config.query;
      console.log(username);
      console.log(password);
      // mock error
      return {
        code: 200,
        message: "测试get接口",
      };
    },
  },
];

使用

  • 新建 request.js
js
import axios from "axios";
import store from "@/store";
import { getToken } from "@/utils/auth";

// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000, // request timeout
});

// request interceptor
service.interceptors.request.use(
  (config) => {
    // do something before request is sent

    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers["X-Token"] = getToken();
    }
    return config;
  },
  (error) => {
    // do something with request error
    console.log(error); // for debug
    return Promise.reject(error);
  }
);

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
   */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  (response) => {
    const res = response.data;
    console.log(res);
    // if the custom code is not 20000, it is judged as an error.
    if (res.code !== 200) {
      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      return Promise.reject(new Error(res.message || "Error"));
    } else {
      console.log("进来了啊");
      return res;
    }
  },
  (error) => {
    console.log("err" + error); // for debug
    return Promise.reject(error);
  }
);

export default service;
  • 使用方法
bash
post 对应的就是 data,get 对应的就是 params
js
import request from "@/utils/request";

export const loginApi = (data) => {
  return request({
    url: "/api/loginpost",
    method: "post",
    data,
  });
};

export const loginApi2 = (params) => {
  return request({
    url: "/api/loginget",
    method: "get",
    params,
  });
};

在 vue 中使用

js

handleclickpost() {
    loginApi({
      username: "admin",
      password: "123456",
    }).then((res) => {
      console.log(res);
    });
},