1.安装axios
npm i axios
环境配置.png
.env.development.png
.env.production.png
.env.test.png
package.json.png
2.新建一个axios.js文件,对axios进行封装
import axios from 'axios'
import QS from 'qs' // 引入qs模块,用来序列化post类型的数据
import jsonBig from 'json-bigint' // 解决后端返回大数字问题(控制台中preview和response值不同)
import store from '@/store/index' // 导入vuex,因为我们要使用到里面的状态对象
import { Message, Loading } from 'element-ui';
// 请求加载
let loading:any
let needLoadingRequestCount = 0
function showLoading () {
if(needLoadingRequestCount === 0) {
loading = Loading.service({
lock: true,
text: '加载中...',
background: 'rgba(0,0,0,0.2)'
})
}
}
function hideLoading () {
if(needLoadingRequestCount <= 0) return
needLoadingRequestCount--
if(needLoadingRequestCount === 0) {
loading.close()
}
}
// axios基本配置信息:baseURL、设置请求超时、请求头设置
const instance = axios.create({
baseURL: process.env.VUE_APP_DATA_URL,
timeout: 10000, // 若为0表示无超时时间
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
try {
// 如果转换成功则返回转换的数据结果
return jsonBig.parse(data)
} catch (err) {
// 如果转换失败,则包装为统一数据格式并返回
return {
data
}
}
}]
})
// 携带当前页面路径跳转登录页,登录完成后返回当前页面
const toLogin = () => {
router.replace({
path:'/login',
query:{
redirect:router.currentRoute.fullPath
}
})
}
// 提示函数
const tip = msg => {
Message({
icon: 'warning',
message:msg
})
}
// 请求拦截
instance.interceptors.request.use(
config => {
/*
每次发送请求之前判断vuex中是否存在token
若存在,统一在http请求的header上都加上token,后台根据token判断你的登录情况
即使本地存在token也有可能是过期的
所以在响应拦截器中对返回状态进行判断
token
一般登录完成,将用户的token通过localstorage或cookie存在本地
用户在每次进入页面的时候,先从本地存储中读取token
若token存在则说明用户已经登录过,更新vuex中的token状态
每次请求接口的时候,请求头中携带token,后台判断携带的token是否过期
若未携带,则说明没有登录过
*/
showLoading()
const token = store.state.token
token && (config.headers.Authorization = token)
return config
},
error => {
hideLoading()
return Promise.error(error)
}
)
// 响应拦截:服务器返回给我们的数据,进行统一的处理
instance.interceptors.response.use(
response => {
hideLoading()
if(response.status === 200){
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
},
/*
以下是服务器状态码不是2开头的情况,和后台人员协商好统一的错误状态码
*/
error => {
hideLoading()
if (error.response.status) {
switch (error.response.status){
// 401未登录,携带当前页面路径跳转至登录页面,登录成功跳转至当前页
case 401:
toLogin()
break;
// 403 token过期,对用户进行过期提示,清除本地token和vuex的token对象,跳转至登录页
case 403:
tip('登录过期,请重新登录')
localStorage.removeItem('token');
store.commit('loginSuccess', null);
setTimeout(() => {
toLogin()
}, 1000);
break;
// 404请求不存在
case 404:
tip('网络请求不存在')
break;
// 其他错误,直接抛出错误提示
default:
tip(error.response.data.message)
}
return Promise.reject(error.response)
}
}
)
// get方法的封装(url-请求的地址,params-请求的参数)
export function get(url,params){
return new Promise((resolve,reject)=>{
instance.get(url,{
params:params
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err.data)
})
})
}
// post方法的封装(url-请求的地址,params-请求的参数)
export function post(url,params){
return new Promise((resolve,reject)=>{
instance.post(url,QS.stringify(params)).then(res => {
resolve(res.data)
}).catch(err => {
reject(err.data)
})
})
}
3.api.js(api的统一管理,模块化)
// address.js
import { get, post } from './axios.js'
const address = {
// 如一个post请求的接口,url: http://www.baiodu.com/api/v1/users/my_address/address_edit_before
apiAddress(p){
return post('api/v1/users/my_address/address_edit_before', p)
},
apiAddressDetail(p){
return post('api/v1/users/my_address/address_detail', p)
}
}
export default address
// index.js
import address from 'api/address.js'
import article from 'api/article.js'
...// 其它模块的接口
export default {
address,
article
}
// main.js
import Vue from 'vue'
import App from './App'
import router from './router' // 导入路由文件
import store from './store' // 导入vuex文件
import api from './api/index' // 导入api接口
Vue.prototype.$api = api // api挂载到vue原型上
4.封装好的接口调用
export default{
name:'',
created(){
this.onLoad()
},
methods:{
onLoad(){
this.$api.address.apiAddress({
type:0,sort:1
}).then(
res=>{
// 获取数据成功的其它操作
}
)
}
}
}
网友评论