在理论的我的项目中,和后盾的数据交互是少不了的,我通常应用的是 axios 库,所以以下示例也是以 axios 为根底来进行封装的。如果对 axios 不理解的,请看这里 axios 文档
1、装置
首先是 npm 装置 axios 很简略:npm install axios
2、没有封装存在的问题
如果在没有封装接口的我的项目中,在文件中随处能够看到如下的接口调用办法:
this.$axios.post("/user/add", { params: { name: this.name, age: this.age }}).then(res => { console.log(res)}).then(err => { console.log(err)})
这样写也不是不能够,但存在一些缺点,接口申请的 url 分布在各个文件中,如果须要在接口调用胜利或失败时做一些解决,就须要更改每个文件。所以把这些接口申请对立集中起来,如果有调整,间接在集中文件中找到批改就好了,而不必再去查每个文件。
3、创立文件
首先在我的项目的 src 目录中,新建文件夹及文件目录构造如下:
├── src 源码目录│ ├── apis 接口文件目录│ │ ├── login.api.js 登录模块的接口 api│ │ └── user.api.js 用户模块的接口 api│ ├── services 申请相干文件目录│ │ ├── address.js 申请地址配置文件│ │ └── request.js axios封装,申请拦挡、响应码解决等操作
api接口文件模块的划分,大能够依据本人的理论我的项目,按业务性能或业务逻辑或其余模式划分。
4、申请地址配置
个别咱们的我的项目环境都会有多个,少的也会有开发环境和生产环境。失常状况下,在开发环境下和生产模式下有着不同的 baseURL,所以,咱们须要依据不同的环境切换不同的 baseURL。
address.js 文件:
// 依据 process.env.NODE_ENV 切换不同的 baseURLconst isPro = process.env.NODE_ENV === 'production'module.exports = { // 'apis':vue.config.js中proxy设置的代理 baseURL: isPro ? 'http://192.168.100.120/ceds' : '/apis' }
5、axios 配置(设置申请头、响应码解决)
大体思路是通过封装一个request类,其中蕴含了get、post等申请办法,这些申请办法又都会去调用 request 办法,该办法通过传入的不同参数调用原始的 axios 申请,而后返回一个 Promise。
request.js 文件:
import axios from 'axios'import Qs from 'qs'import Vue from 'vue'import { getToken } from '@Utils/session.utils' // 存储获取token文件import address from './address' // 申请地址class Request { constructor () { // 创立axios实例 this._axios = axios.create({ baseURL: address.baseURL, timeout: 1000 * 5, // 申请超时工夫 headers: {} }) // 申请拦挡 this._axios.interceptors.request.use( config => { const requestHeader = { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json; charset=UTF-8', 'Access-Control-Allow-Origin': '*', token: getToken() // 申请头对立增加token } config.headers = Object.assign(config.headers, requestHeader) return config }, error => { Promise.reject(error) } ) } // 依据申请形式,判断参数是放在query中还是body中。 // 最直观的区别,比方GET申请把参数蕴含在url中,而POST则通过request body把参数搁置在body体中,所以在提交时的参数模式是有区别的 // 以下列了四种我个别罕用申请形式的参数模式,大家能够自行调整 /** * 发送get申请 * @param {String} url地址 * @param {Object} query 查问参数 * @return json数据 */ get (url, query = {}) { return this._request('get')(url, { ...query }) } /** * 发送post申请 * @param {String} url地址 * @param {Object} body 查问参数 * @return json数据 */ post(url, body = {}, headers) { let data if(this.isFormData(body)) { data = body } else if(Array.isArray(body)) { data = body } else { data = { ...body } } return this._request('post')(url, headers)(url, data) } put (url, body = {}) { return this._request('put')(url, { ...body }) } delete(url, body = {}) { return this._request('delete')(url, { ...body }) } isFormData = v => { return Object.prototype.toString.call(v) === '[object FormData]' } /** * 设置申请头 * @param {Object} header 申请头 */ setHeaders (header) { Object.keys(header).forEach(key => { this._axios.defaults.headers[key] = header[key] }) } // 解决申请头 headers handleHeaders () { const headers = {} headers['XMIME-TYPE'] = '3' Headers['Content-Type'] = 'application/json; charset=UTF-8' return headers } /** * 发送申请 * @param {String} method 申请办法类型 * @param headers * @returns {function(*=, *=):Promise<unknown>} * @private */ _request (method, headers) { this.setHeaders(this.handleHeaders()) // 设置对立的申请头 if (headers) { this.setHeaders(headers) // 自定义申请头 } return (url, data, timeout) => { const config = { url, method, timeout: timeout || this._axios.defaults.timeout } // 结构申请 config // 判断申请类型 get post const paramType = ['get', 'delete'].indexOf(method) !== -1 ? 'params' : 'data' config[paramType] = data //参数序列化 config.paramsSerializer = params => { return Qs.stringify(params, { arrayFormat: 'repeat' }) } return new Promise((resolve, reject) => { // 发送真正的申请,验证权限,查看404等status this._axios .request(config) .then(response => { if (this.handleSuccessStatus(response.data.code, response.data)) { if (response.headers['content-type'] !== 'text/plain; charset=urf-8') { resolve( // 对响应后果二次包装 Object.assign( { success: Number(response.data.code) === 200, data: response.data.data, msg: response.data.msg }, response.data ) ) // 解决返回后果 } else { resolve(response.data) } } }, response => { // 解决错误码 if(response.response) { const statusCode = response.response.status this.handleErrorStatus(statusCode) } else { Vue.prototype.$message.error(response.message) } reject(response) }) .catch(err => { reject(err) }) }) } } } // 申请胜利,返回错误码 // 具体状态码跟后盾开发人员对立,而后依据状态码进行相应提醒 // 上面是我在我的项目中的操作,大家可自行调整扩大 handleSuccessStatus (code, data) { let result = '' let flag = false switch (code) { case '20007': result = '未查找到二次认证明码!' flag = true break case '20008': result = '您的二次认证明码还未修改,请先批改!' flag = true break case '20009': result = '您还未开启二次认证,请分割管理员!' flag = true break case '90001': result = '请输出二次认证明码!' flag = true break case '90002': result = '无操作权限!' flag = true break default: break } // 进行告诉 // $message办法是我按需引入的element-ui中的提醒组件,你能够替换成本人的提醒组件 if (result) { Vue.prototype.$message.error(result) } return flag } // 依据错误码获取谬误提醒 handleErrorStatus (statusCode) { let errorMsg = '' if (statusCode === 500) { errorMsg = '数据申请失败,请分割管理员!' } else if (statusCode === 404) { errorMsg = '申请地址谬误!' } else if (statusCode === 402) { errorMsg = '以后您没有权限操作该数据!' } else { errorMsg = '申请出错!' } // 进行告诉 Vue.prototype.$message.error(errorMsg) }}export default new Request()
6、应用
咱们在接口管理文件中,通过调用下面封装的 request 类,传入对应的参数即可。
user.api.js 文件:
import http from '../services/request'/** * @description 获取用户列表 * @param {*} params 申请接口的参数 */// 此处定义的reqUserList办法会调用咱们封装的request中的get办法,get办法的第一个参数是申请地址,第二参数是query参数export const reqUserList = params => http.get('/user/list', params)
在调用的 .vue 文件中,引入该办法并传入参数即可
import { reqUserList } from '@Apis/user.api' // 导入apiexport default { name: 'UserList', ... ... created() {}, methods: { async getUsers() { // 调用api接口,并传入参数 const res = await reqUserList({ page: 1, size: 10 }) console.log(res) // 获取的响应后果 } }}
如此,就实现了对接口的封装及根本应用。
PS:以上这些文件名、文件夹名、办法名、门路等都是我本人获得,你能够依照本人的代码格调习惯进行调整。
以上,是我在我的项目中的一些写法,有的中央可能不欠缺,如有问题欢送大家斧正,感激 :)