开发一个自动生成接口文件且带mock功能的工具

开发一个自动生成接口文件且带mock功能的工具

痛点是:

  1. 写接口的api文件(如下),比较麻烦。大多数接口,都是同一种格式,要么get要么post。每次都是重复性的写。
    • 根据DRY(don’t repeat yourself)原则,我们尝试把这个自动化
    // 这是 api文件, 每次都要重复性的写
    
    import { axios } from './myAxios.js'
    
    export const xxxxList = (data) => {
      return axios({
        method: 'post',
        url: '/xxx/xxx',
        data
      })
    }
    
    export const xxxxupdate = (data) => {
      return axios({
        method: 'post',
        url: '/xxx/xx',
        data
      })
    }
    
    export const xxxx = (params) => {
      return axios({
        method: 'get',
        url: '/xxxx/xxxx',
        params
      })
    }
    复制代码

尝试用工具把这个自动化实现了

功能要求

  1. 能自动生成对应的接口文件
  2. 并带mock功能
  3. 且小组成员都可以很容易的使用

设计思路:

在项目根目录下 根据一个配置文件(比如:fe.config.js) 去生成对应的接口文件,并带mock功能

  • 配置文件如下
// fe.config.js
module.exports = {
  // apiAndMock:此处适用于apiAndMock的模块,其他工具有其的key
  apiAndMock: {
    config: { // 会根据此处的对象,自动生成对应的api文件
      reportList: { // 会生成reportList.js ( 有n个key, 则生成n个[key].js )
        getReportList: {
          url: '/getReportList',
        },
        addReport: {
          url: '/addReport',
          method: 'post' // 自动处理成data, 不写的话, 默认get请求
        },
        updateReport: {
          url: '/updateReport',
          method: 'post' // 自动处理成data, 不写的话, 默认get请求
        },
        deleteReports: {
          url: '/deleteReports',
          method: 'post' // 自动处理成data, 不写的话, 默认get请求
        }
      }
    }
  }
}
复制代码

难点

  1. 难点1:用户可能会对axios(或其他)做一层包装,比如增加 请求拦截 或 响应拦截(比如做一些鉴权)。

    • 此时当前的项目,就需要用到用户封装过的axios。
    • 解决办法:增加一个配置项 myAxios,如下。建议写别名@,代表src目录
      • 还需增加 myAxiosInstance,因为有些项目直接import导入 instance 就能使用,但有些项目需要instance.instance 才能使用
      module.exports = {
        apiAndMock: {
        + myAxios: "import instance from '@/axios/index.js'", // 建议写别名@,代表src目录,
        + myAxiosInstance: 'instance.instance',
          config: { // 会根据此处的对象,自动生成对应的api文件
            reportList: { // 会生成reportList.js ( 有n个key, 则生成n个[key].js )
              ...
            }
          }
        }
      }
      复制代码

      什么是封装过的axios?

      • 举个例子:这是我的项目内的axios/index.js,也是封装过的axios

        // axios/index.js
        
        ...
        
        // 创建axios实例
        const instance = axios.create({
          ...
        })
        
        // 添加请求拦截器
        instance.interceptors.request.use(function (config) {
          ...
          return config
        }, function (error) {
          ...
        })
        
        // 添加响应拦截器
        instance.interceptors.response.use(function (response) {
          ...
          return response
        }, function (error) {
          ...
        })
        
        // 初始化
        function install (Vue, opt) {
          // 添加全局方法
          Vue.prototype.$axios = instance
        }
        
        export default {
          install,
          instance
        }
        复制代码
  2. 难点2:也算是需求点,希望能一并完成mock功能

    设计思路,增加一个data字段,mock模式下会用到,不影响接口文件

    module.exports = {
     // apiAndMock:此处适用于apiAndMock的模块,其他工具有其的key
     apiAndMock: {
       myAxios: "import instance from '@/axios/index.js'", // 建议写别名@,代表src目录,
       myAxiosInstance: 'instance.instance',
       config: { // 会根据此处的对象,自动生成对应的api文件
         reportList: { // 会生成reportList.js ( 有n个key, 则生成n个[key].js )
           getReportList: {
             url: '/getReportList',
           + data: [ // 生成mock时, 才会用到此处的data
           +   {
           +     id: 1,
           +     reportName: '234',
           +     reportTitle: '33423',
           +     topicIds: '24,3,2',
           +     status: 0,
           +     startDate: '2020-11-01',
           +     lateDays: 5,
           +     createUser: 'xxx.li',
           +     updateUser: 'xx.li',
           +     createTime: '2020-11-18 14:04:17',
           +     updateTime: '2020-11-18 14:04:17'
           +   },
           +   {
           +     id: 2,
           +     reportName: '234',
           +     reportTitle: '33423',
           +     topicIds: '24,3,2',
           +     status: 0,
           +     startDate: '2020-11-01',
           +     lateDays: 5,
           +     createUser: 'xxx.li',
           +     updateUser: 'xx.li',
           +     createTime: '2020-11-18 14:04:17',
           +     updateTime: '2020-11-18 14:04:17'
           +   }
           + ]
           },
           addReport: {
             url: '/addReport',
             method: 'post' // 自动处理成data, 不写的话, 默认get请求
           },
           updateReport: {
             url: '/updateReport',
             method: 'post' // 自动处理成data, 不写的话, 默认get请求
           },
           deleteReports: {
             url: '/deleteReports',
             method: 'post' // 自动处理成data, 不写的话, 默认get请求
           }
         }
       }
     }
    }
    复制代码

    具体的实现,下面有详解

  3. 难点3:小组成员都可以很容易的使用

    解决方法:又需要用到我们的工具平台了内部前端工具平台搭建

    npm install -g @company/feTools 后

    // 注意 1. 命令需在根目录下执行
    //     2. 需提前配好配置文件 fe.config.js
    //     3. 输出的文件会在:`src/api`  内
    fe mock      // mock模式
    fe api       // api模式(标准模式)
    fe api-pkg   // api模式(处理一下响应结果,只返回响应数据的data,不反回header等等。兼容一些老项目)
    复制代码

难点2详解:如何实现mock功能

  1. 首先看看mock功能如何实现
  2. 在考虑把mock功能自动化

1. 首先看看mock功能如何实现

只需在任意地方引入 myMock/index.js 就能让mock生效了

  • 使用axios-mock-adapter库,这库的原理是:会拦截axios的请求,如果匹配到了对应的path,会响应出对应的data(下方有配置)
mock文件夹的目录结构如下:

myMock
    reportList.js
    index.js
    
只需在任意地方引入 myMock/index.js 就能让mock生效了


// index.js 
var axios = require("axios")
// 使用mock库,这库的原理是:会拦截axios的请求,如果匹配到了对应的path,会响应出对应的data(下方有配置)
var MockAdapter = require("axios-mock-adapter") 
var mock = new MockAdapter(axios)

import { init as reportList } from './reportList' // 引入mock响应文件
reportList(mock)


// reportList.js
export const init = (mock) => {
  mock.onGet('/getReportList').reply(200, {
    data: [
      {"id":1,"reportName":"xxx new","reportTitle":"xxxx","topicIds":"24,3,2","status":0,"startDate":"2020-11-01","lateDays":5,"createUser":"xxxx.li","updateUser":"xxxx.li","createTime":"2020-11-18 14:04:17","updateTime":"2020-11-18 14:04:17"},
      {"id":2,"reportName":"xxx new","reportTitle":"xxxx","topicIds":"24,3,2","status":0,"startDate":"2020-11-01","lateDays":5,"createUser":"xxxx.li","updateUser":"xxxx.li","createTime":"2020-11-18 14:04:17","updateTime":"2020-11-18 14:04:17"}
    ],
    ret: 0,
    msg: 'ok'
  })

  mock.onPost('/addReport').reply(200, {
    data: [],
    ret: 0,
    msg: 'ok'
  })

  mock.onPost('/updateReport').reply(200, {
    data: [],
    ret: 0,
    msg: 'ok'
  })

  mock.onPost('/deleteReports').reply(200, {
    data: [],
    ret: 0,
    msg: 'ok'
  })
}
复制代码

2. 在考虑把mock功能自动化

有了上面的参考文本后,在结合 配置文件,可以很轻松的实现

根据配置文件,贴上最终得到的结果

配置文件: fe.config.js

// fe.config.js
module.exports = {
  // apiAndMock:此处适用于apiAndMock的模块,其他工具有其的key
  apiAndMock: {
    myAxios: "import instance from '@/axios/index.js'", // 建议写别名@,代表src目录,
    myAxiosInstance: 'instance.instance',
    config: { // 会根据此处的对象,自动生成对应的api文件
      reportList: { // 会生成reportList.js ( 有n个key, 则生成n个[key].js )
        getReportList: {
          url: '/getReportList',
          data: [ // 生成mock时, 才会用到此处的data
            {
              id: 1,
              reportName: '234',
              reportTitle: '33423',
              topicIds: '24,3,2',
              status: 0,
              startDate: '2020-11-01',
              lateDays: 5,
              createUser: 'xxx.li',
              updateUser: 'xx.li',
              createTime: '2020-11-18 14:04:17',
              updateTime: '2020-11-18 14:04:17'
            },
            {
              id: 2,
              reportName: '234',
              reportTitle: '33423',
              topicIds: '24,3,2',
              status: 0,
              startDate: '2020-11-01',
              lateDays: 5,
              createUser: 'xxx.li',
              updateUser: 'xx.li',
              createTime: '2020-11-18 14:04:17',
              updateTime: '2020-11-18 14:04:17'
            }
          ]
        },
        addReport: {
          url: '/addReport',
          method: 'post' // 自动处理成data, 不写的话, 默认get请求
        },
        updateReport: {
          url: '/updateReport',
          method: 'post' // 自动处理成data, 不写的话, 默认get请求
        },
        deleteReports: {
          url: '/deleteReports',
          method: 'post' // 自动处理成data, 不写的话, 默认get请求
        }
      }
    }
  }
}
复制代码

得到的结果:

// 目录结构
api
    myApi
        myAxios.js // 这个文件有2种情况,一种是mock模式,一种是api模式
        reportList.js
    myMock
        index.js
        reportList.js
        
// myApi/myAxios.js   这个文件有2种情况,一种是mock模式,一种是api模式
// fe mock 是mock模式, 引入了mock文件
/* 此文件是自动生成的, 在此修改会不生效 */
import axiosRoot from 'axios' // 用默认的axios
import '../myMock' // 引入了mock文件
export const axios = (obj) => {
  return new Promise((resolve, reject) => {
    axiosRoot(obj)
      .then(e => {
        resolve(e && e.data)
      })
      .catch(err => {
        console.error('接口返回错误: ' + JSON.stringify(err))
        reject(err)
      })
  })
}
console.log('当前是mock模式')
// fe api-pkg 是api模式, 没有引入了mock文件,引入了用户封装过的axios实例
/* 此文件是自动生成的, 在此修改会不生效 */
import instance from '@/axios/index.js'
export const axios = (obj) => {
  return new Promise((resolve, reject) => {
    instance.instance(obj)
      .then(e => {
        resolve(e && e.data)
      })
      .catch(err => {
        console.error('接口返回错误: ' + JSON.stringify(err))
        reject(err)
      })
  })
}


// myApi/reportList.js
/* 此文件是自动生成的, 在此修改会不生效, 修改入口: fe.config.js */
import { axios } from './myAxios.js'

export const getReportList = (params) => {
  return axios({
    method: 'get',
    url: '/getReportList',
    params
  })
}

export const addReport = (data) => {
  return axios({
    method: 'post',
    url: '/addReport',
    data
  })
}

export const updateReport = (data) => {
  return axios({
    method: 'post',
    url: '/updateReport',
    data
  })
}

export const deleteReports = (data) => {
  return axios({
    method: 'post',
    url: '/deleteReports',
    data
  })
}


// myMock/index.js
/* 此文件是自动生成的, 在此修改会不生效, 修改入口: fe.config.js */
var axios = require("axios")
var MockAdapter = require("axios-mock-adapter")
var mock = new MockAdapter(axios)

import { init as reportList } from './reportList'
reportList(mock)
    
    
// myMock/reportList.js
/* 此文件是自动生成的, 在此修改会不生效, 修改入口: fe.config.js */
export const init = (mock) => {
  mock.onGet('/getReportList').reply(200, {
    data: [
      {"id":1,"reportName":"234","reportTitle":"33423","topicIds":"24,3,2","status":0,"startDate":"2020-11-01","lateDays":5,"createUser":"xxx.li","updateUser":"xx.li","createTime":"2020-11-18 14:04:17","updateTime":"2020-11-18 14:04:17"},
      {"id":2,"reportName":"234","reportTitle":"33423","topicIds":"24,3,2","status":0,"startDate":"2020-11-01","lateDays":5,"createUser":"xxx.li","updateUser":"xx.li","createTime":"2020-11-18 14:04:17","updateTime":"2020-11-18 14:04:17"}
    ],
    ret: 0,
    msg: 'ok'
  })

  mock.onPost('/addReport').reply(200, {
    data: [],
    ret: 0,
    msg: 'ok'
  })

  mock.onPost('/updateReport').reply(200, {
    data: [],
    ret: 0,
    msg: 'ok'
  })

  mock.onPost('/deleteReports').reply(200, {
    data: [],
    ret: 0,
    msg: 'ok'
  })
}
复制代码

码字不易,点点小赞鼓励~

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享