开发一个自动生成接口文件且带mock功能的工具
痛点是:
- 写接口的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 }) } 复制代码
尝试用工具把这个自动化实现了
功能要求
- 能自动生成对应的接口文件
- 并带mock功能
- 且小组成员都可以很容易的使用
设计思路:
在项目根目录下 根据一个配置文件(比如: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:用户可能会对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:也算是需求点,希望能一并完成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:小组成员都可以很容易的使用
解决方法:又需要用到我们的工具平台了内部前端工具平台搭建
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功能
- 首先看看mock功能如何实现
- 在考虑把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