在实际的项目中,和后台的数据交互是少不了的,我通常使用的是 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(res) })
这样写不是不可以,但是存在一些缺陷,接口请求的 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:以上这些文件名、文件夹名、方法名、路径等都是我自己取得,你可以按照自己的代码风格习惯进行调整。
以上就是如何在Vue项目中使用axios请求的详细内容,更多关于Vue项目中使用axios的资料请关注其它相关文章!
暂无评论内容