共计 5222 个字符,预计需要花费 14 分钟才能阅读完成。
在理论的我的项目中,和后盾的数据交互是少不了的,我通常应用的是 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 切换不同的 baseURL
const 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' // 导入 api
export default {
name: 'UserList',
... ...
created() {},
methods: {async getUsers() {
// 调用 api 接口,并传入参数
const res = await reqUserList({
page: 1,
size: 10
})
console.log(res) // 获取的响应后果
}
}
}
如此,就实现了对接口的封装及根本应用。
PS:以上这些文件名、文件夹名、办法名、门路等都是我本人获得,你能够依照本人的代码格调习惯进行调整。
以上,是我在我的项目中的一些写法,有的中央可能不欠缺,如有问题欢送大家斧正,感激 :)