axios封装&拦截器
目录
1、初始化vue项目
# vue init webpack deaxios
# npm install axios -S
# cnpm install vuex -S
# cnpm install vant -S
# cnpm install nprogress -S
2、封装axios(创建 scr/api 文件夹)
2.1、配置全局url变量
// 路径: config/urls/url.js
export default{
// api请求地址
API_URL:'http://127.0.0.1:8000/'
}
2.2、封装axios请求
// 路径: srcapiajax.js
improt Qs from 'qs'
import instance from './axiosinstance' //导入自定义axios 实例
// import instance from 'axios' 也可以直接使用原生 axios 实例,但无法添加拦截器
export function get(url,params){
return new Promist((resolve,reject)=>{
// 1、发送get请求
instance({
url:url,
method:'get',
params:params,
headers:{
'Content-Type':'application/json'
},
paramsSerializer:params=>{
return Qs.Stringify(params,{indices:false})
},
}) // 2、回调函数
.then(res=>{
reslove(res.data)
})// 3、捕获异常
.catch(err =>{
reject(err.data)
});
});
}
/* 2.发送POST请求 */
export function post(url,params){
return new Promise((resolve,reject) => {
instance({
url:url // 1、请求地址
method:'post' // 2、请求方法
data: Qs.stringify( // 3、可选函数、序列化'data'
params, //4、提交数据
{ indices:false } // indices:false
),
headers:{
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
})
// 回调函数
.then(res =>{
resolve(res.data)
})
// 捕获异常
.catch(err => {
reject(err.data)
})
});
}
2.3、自定义axios实例
// 路径:srcapiaxiosinstance.js
import Axios from 'axios'
import { Toast } from 'vant'
import URLS from '../../config/urls'
// 1、使用自定义配置新建一个axios实例
const instance = Axios.create({
baseURL:URL.API_URL,
responseType:'json',
});
// 2、添加请求拦截器:每次发送请求就会调用次拦截器,添加认证token
instance.interceptors.request.use(
config => {
// 发送请求前添加认证token,
config.headers.Authorization = sessionStorage.getItem('token')
return config
},
err => {
return Promise.reject(err)
});
// 3、相应拦截器
instance.interceptors.response.use(
response =>{
if(response.status ===200){
return Promise.resolve(response);
} else{
return Promise.reject(response);
}
},
// 服务器状态码不是200的情况
error =>{
if(error.response.status){
switch(error.response.status){
// 401:未登录
// 未登录则跳转登陆页面,并携带当前页面的路径
// 在登陆成功后返回当前页面,这一步需要在登陆页操作。
case 401:
router.replace({
path:'/login',
query:{ redirrect:router.currentRoite.fullPath}
},1000);
break;
// 404 请求不存在
case 404:
Toast({
message:'网络请求不存在',
duration:1500,
forbidClick:true
});
break;
// 其他错误,直接抛出异常
default:
Toast({
message:error.response.data.message,
duration:100,
forbidClick:true
});
}
return Promise.reject(error.response)
}
}
);
export default instance
2.4、导出api模块
// 路径: srcapiindex.js
import * as api from './api'
export default api
2.5 全局导出路由方法变量
// 路径:srcstoreindex.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as api from '../api/api'
Vue.use(Vuex);
export default new Vuex.Store({
modules:{
api
}
});
2.6、使用钩子函数进行路由控制
// 路径:main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import NProgress from 'nprogress'
import store from './store/index'
Vue.config.productionTip = false
/* 定义:路由钩子主要是给使用者在路由发生变化时进行一些特殊的处理而定义的函数 */
router.afterEach(transition => {
setTimeout(() => {
NProgress.done()
})
})
window.APP_INFO = process.env.APP_INFO
router.beforeEach((to, from, next) => {
/*
* to: router即将进入的路由对象
* from: 当前导航即将离开的路由
* next: 进行管道中的一个钩子,如果执行完了,则导航的状态就是 confirmed (确认的);否则为false,终止导航。
* */
NProgress.start()
// 使用假数据模拟张三已经登录
localStorage.setItem('user', JSON.stringify({'username':'zhangsan'}) )
if (to.path === '/login') {
localStorage.removeItem('user')
}
let user = JSON.parse(localStorage.getItem('user'))
if (!user && to.path !== '/login') { // 如果用户没有登录,且访问url不是 '/login' 调整到登录页
next({ path: '/login' })
} else {
next()
}
})
/* 拦截器介绍位置 */
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})