7.如果前端拿到401的状态码,则清空token信息并跳转登录页。
具体实现过程
1.安装vuexnpm install vuex // 安装vuex2.建立store文件夹,创建index.js文件此时vuex里面主要存储token的相关信息,代码如下:
import { createStore } from "vuex"; // 用Vuex.Store对象用来记录token const store = createStore({ state: { // 存储token token:"", userName:"" ,// 可选 passWord:"" }, getters: { getToken(state){ return state.token || localStorage.getItem("token") || ""; } }, mutations: { // 堆代码 duidaima.com // 修改token,并将token存入localStorage setToken(state,token) { state.token = token; console.log('state.token: ', state.token); localStorage.setItem('token', token); console.log('store、localstorage保存token成功!'); }, delToken(state) { state.token = ""; localStorage.removeItem("token"); }, // 可选 setUserInfo(state, userName) { state.userName = userName; } }, actions: { // removeToken: (context) => { // context.commit('setToken') // } }, }); export default store;3.在main.js中引用
import store from './store'4.封装axios
npm install axios; // 安装axios5.创建network文件夹,再创建request.js文件.
/* * @堆代码 duidaima.com * @Date: 2023-10-14 16:28:07 */ import qs from 'qs' import axios from 'axios' import store from '../store/index' import { ElMessage } from 'element-plus' import router from '../router/index' // 使用自定义的配置文件发送请求 const instance = axios.create({ baseURL: '', timeout: 80000, headers: { // 'Content-Type': 'application/json;charset=UTF-8', // 'custome-header':'tianliangjiaoyu' } }) // post请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,即设置post的请求头为 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; // 添加请求拦截器 instance.interceptors.request.use(function (config) { // 每次发送请求之前判断vuex中是否存在token // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况 // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 const token = store.getters.getToken; console.log('token: ', token); if (token) { // 已经登录成功,统一添加token config.headers.Authorization = `Bearer ${token}` } // token && (config.headers.Authorization = token); return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }) instance.interceptors.response.use(function (response) { if (response.status === 200) { return Promise.resolve(response); } else { return Promise.reject(response); } }, function (error) { // 对响应错误做点什么 if (error.response.status) { switch (error.response.status) { // 401: 未登录 // 未登录则跳转登录页面,并携带当前页面的路径 // 在登录成功后返回当前页面,这一步需要在登录页操作。 case 401: router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); break; // 403 token过期 // 登录过期对用户进行提示 // 清除本地token和清空vuex中token对象 // 跳转登录页面 case 403: ElMessage({ message: '登录过期,请重新登录', duration: 1000, type: 'success' }); // 清除token localStorage.removeItem('token'); store.commit('loginSuccess', null); // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面 setTimeout(() => { router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); }, 1000); break; // 404请求不存在 case 404: ElMessage({ message: '网络请求不存在', duration: 1500, type: 'success' }); break; // 其他错误,直接抛出错误提示 default: ElMessage({ message: error.response.data.message, duration: 1500, type: 'success' }); } return Promise.reject(error.response); } }); //封装对应的方法 const $get = (url, params) => { return new Promise((resolve, reject) => { axios.get(url, { params: params, }) .then(res => { resolve(res.data); }) .catch(err => { reject(err.data) }) }); } /** * post方法,对应post请求 * @param {String} url [请求的url地址] * @param {Object} params [请求时携带的参数] */ const $post = (url, params) => { return new Promise((resolve, reject) => { axios.post(url, qs.stringify(params)) //是将对象 序列化成URL的形式,以&进行拼接 .then(res => { resolve(res.data); }) .catch(err => { reject(err.data) }) }); } //下面是vue3必须加的,vue2不需要,只需要暴露出去get,post方法就可以 export default { install: (app) => { app.config.globalProperties['$get'] = $get; app.config.globalProperties['$post'] = $post; app.config.globalProperties['$axios'] = axios; } }此时需要理解一下如何封装axios,
3.封装get,post,put,delete等请求方法
import { createRouter, createWebHashHistory } from 'vue-router' const router = createRouter({ history: createWebHashHistory(), // hash模式:createWebHashHistory,history模式:createWebHistory routes: [ { path: "/", name: "Home", component: () => import("@/views/Home"), }, { path: "/home", name: "Home", component: () => import("@/views/Home"), }, { path: "/404", name: "404", component: () => import("@/views/404"), }, { path: "/notAllow", name: "notAllow", component: () => import("@/views/notAllow"), }, { path: "/login", name: "Login", component: () => import("@/views/Login"), meta: { noLogin: true, //无须登录即可浏览 }, }, ] }) export default router登录进去时有一些路由是所有人可见,设置为默认路由。
router.beforeEach((to, from, next) => { const isLogin = localStorage.token ? true : false console.log('isLogin: ', isLogin); console.log("navigationList", navigationList) console.log("11111111111111", store.state.asyncRoutestMark) if (isLogin) { if (!store.state.asyncRoutestMark) { navigationList.forEach(navigation => { router.addRoute('home', { path: navigation.url, meta: { name: navigation.name, isAsync: true, icon: navigation.icon }, name: navigation.url, component: () => import(`../views/${navigation.url}`) }) }) console.log(router.getRoutes(), '查看现有路由') console.log("to",to) store.commit('changeRouter', true) store.commit("setAllRoutes",router.getRoutes()) next({ ...to, replace: true }) }else { next() } }else { next() } })