📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍
文章目录
- 写在前面的话
- 前端请求工具封装
- 封装思路
- 实例 Demo
- 细节说明
- 总结陈词
写在前面的话
前篇博文介绍了,前后端分离实战项目中,关于统一返回结果的封装。
本篇博文就接着介绍一下,前端 Axios 插件封装思路,以及对于这一返回封装结果的接受处理。
加油,程序猿,保持住Tempo,开干,玩的就是真实!
关联文章:
《程序猿入职必会(1) · 搭建拥有数据交互的 SpringBoot 》
《程序猿入职必会(2) · 搭建具备前端展示效果的 Vue》
《程序猿入职必会(3) · SpringBoot 各层功能完善 》
《程序猿入职必会(4) · Vue 完成 CURD 案例 》
《程序猿入职必会(5) · CURD 页面细节规范 》
《程序猿入职必会(6) · 返回结果统一封装》
前端请求工具封装
封装思路
Vue 项目中,可以使用的请求插件很多,这边选用之前已整合完毕的 Axios 展开说明,其他技术类似。
前端请求工具类应该具备哪些特性?
- 提取所有请求的公用部分,例如后端服务前缀、超时时间、公用请求头等
- 具备请求前置拦截逻辑,可以针对请求头和参数进行封装,也可以做前端鉴权动作
- 具备请求后置拦截逻辑,可以针对响应内容进行解析处理,针对不同状态码做出不同应对
- 对外提供丰富便捷的调用方法,方便页面和组件快速使用
实例 Demo
这里先基于上述的封装思路,展示一段已实现的效果,再拆分说明。
【封装工具类】
/**
* Http 请求封装工具类
* Axios是基于http客户端的promise,面向浏览器和NodeJS
* Created by LinWang on 2020/08/08.
*/
import axios from 'axios'
import qs from 'qs'
import store from '../store'
import { Message, MessageBox } from 'element-ui'
import { getToken } from '@/utils/auth'
import _ from 'lodash'
import { showFullScreenLoading, tryHideFullScreenLoading } from './loadService'
/**
* 创建Axios实例
*/
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, timeout: process.env.TIME_OUT
})
service.all = axios.all
service.spread = axios.spread
/**
* 添加一个请求拦截器(前置)
*/
service.interceptors.request.use(config => {
showFullScreenLoading()
if (_.isObject(config.data)) {
config.data = qs.stringify(config.data, { allowDots: true })
}
config.headers['Content-Type'] = 'application/x-www-form-urlencoded' // 默认为 application/json
config.headers.operator = getToken() // 让每个请求携带自定义token,请根据实际情况自行修改
config.headers.requestId = new Date().getTime() // 请求时间点
return config
}, error => {
console.log(error)
Promise.reject(error)
})
/**
* 添加一个返回拦截器(后置处理)
*/
service.interceptors.response.use(response => {
tryHideFullScreenLoading()
const res = response.data
if (response.status !== 200 || !res.success) {
Message({
message: res.message, type: 'warning', duration: 5 * 1000
})
// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
}
return Promise.reject(res)
} else {
return res.data
}
}, error => {
tryHideFullScreenLoading()
console.log('err' + error)
Message({
message: error.error, type: 'warning', duration: 5 * 1000
})
return Promise.reject(error)
})
export default service
【框架整合工具类】
Tips:就main.js添加两行代码即可,$http是添加到全局,可以快速使用
import http from '@/utils/request'
Vue.prototype.$http = http
【某个实体对应 api.js - 代码生成】
import request from '@/utils/request'
export default {
getList(params) {
return request({
url: '/zyTeacherInfo/', method: 'get', params
})
},
get(params) {
return request({
url: '/zyTeacherInfo/' + params.teaCode, method: 'get', params
})
},
getPage(params) {
return request({
url: '/zyTeacherInfo/page', method: 'get', params
})
},
update(params) {
return request({
url: '/zyTeacherInfo/update', method: 'post', params
})
},
insert(params) {
return request({
url: '/zyTeacherInfo/insert', method: 'post', params
})
},
remove(params) {
return request({
url: '/zyTeacherInfo/delete', method: 'post', params
})
}
}
【页面使用示例】
// 引入api.js
import ZyTeacherInfoApi from '@/api/study/ZyTeacherInfoApi'
// 通过实体对应api.js,触发删除逻辑
handleDelete(row) {
let that = this
ZyTeacherInfoApi.remove({ teaCode: row.teaCode }).then(() => {
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 1000,
onClose() {
that.fetchData()
}
})
})
},
// 利用工具类的all方法,并联查询多个接口
this.$http.all([ZyTeacherInfoApi.getPage(this.listQuery)])
.then(this.$http.spread(function(perms) {
that.list = perms.rows
that.total = perms.total
that.listLoading = false
}))
细节说明
【基础 Axios】
整个请求工具类的核心就是 Axios。
使用 axios.create 创建一个 Axios 实例,然后设置后端服务前缀、超时时间等,这些属性都配置再项目配置文件中。
将 axios.all 和 axios.spread,添加到上述实例,方便快速复用。
代码段参考:
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, timeout: process.env.TIME_OUT
})
service.all = axios.all
service.spread = axios.spread
【添加 Axios 请求拦截器】
利用 service.interceptors.request.use 添加请求拦截器,里面按如下步骤执行:
- 显示全屏 Loading 效果,这个是自己封装的,也可以采用外部插件;
- 设置 Content-Type,按指定的入参类型组装参数;
- 设置操作人、时间戳等其他请求头信息;
service.interceptors.request.use(config => {
showFullScreenLoading()
if (_.isObject(config.data)) {
config.data = qs.stringify(config.data, { allowDots: true })
}
config.headers['Content-Type'] = 'application/x-www-form-urlencoded' // 默认为 application/json
config.headers.operator = getToken() // 让每个请求携带自定义token,请根据实际情况自行修改
config.headers.requestId = new Date().getTime() // 请求时间点
return config
}, error => {
console.log(error)
Promise.reject(error)
})
【添加 Axios 响应拦截器】
利用 service.interceptors.request.use 添加请求拦截器,里面按如下步骤执行:
- 响应成功和失败,都需要关闭 Loading 效果;
- 根据 code 状态码判断失败与否;
- 如果是成功的话,将数据返回给调用方;
- 如果是报错的话,返回报错信息给调用发,同时利用提示信息组件,展示提示;
service.interceptors.response.use(response => {
tryHideFullScreenLoading()
const res = response.data
if (response.status !== 200 || !res.success) {
Message({
message: res.message, type: 'warning', duration: 5 * 1000
})
// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
}
return Promise.reject(res)
} else {
return res.data
}
}, error => {
tryHideFullScreenLoading()
console.log('err' + error)
Message({
message: error.error, type: 'warning', duration: 5 * 1000
})
return Promise.reject(error)
})
总结陈词
此篇文章介绍了前端 Axios 插件封装思路,仅供学习参考。
Axios 官网用法很多,丰富多彩,但实战中,上述提供的示例已经覆盖了大部分常用用法了。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。