【Vue基础】路由守卫+白名单
程序员文章站
2022-02-28 06:20:34
...
路由守卫+白名单
目录:
核心代码演示:
import router from "./index";
import store from "../store/index";
import { getToKen, removeToKen, removeUserName } from "@/utils/app";
//白名单
const whiteRouter = ['/login']; //indexOf方法,判断数组中是否存在指定的某个对象,如果不存在,则返回-1
//全局路由守卫 beforeEach:路由改变都会触发
router.beforeEach((to, from, next) => {
/**
* next():执行了to里面的路由对象,进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
*
* 1.不带参数:指向(进入)to钩子--进入下一个页面,但是不会触发beforeEach
* 2.带参数next('/')或者next({path:'/'}):进入指定页面,发生路由变化,有变化就会触发beforeEach --- 问题:容易造成死循环--比如next('/index'),当执行到这里的时候,触发beforeEach,又遇到里面的next('/index'),又触发next('/index')......
*
* 如果要进入下一个页面,直接next()--进入to钩子,调用to里面的路径,往下一个页面跑
*
* console.log(to) // 进入的页面(下一个页面)
* console.log(from) // 离开之前的页面(上一个页面)
* console.log(next) // next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。确保要调用 next 方法,否则钩子就不会被 resolved。
*
* to.path:进入的下一个页面的路径
*
*/
//token令牌--处理权限
//console.log(to) //index -->在login页面直接输入url跳转到index。 to.path == index
if (getToKen()) {
if (to.path === '/login') {
removeToKen();
removeUserName();
store.commit('app/SET_TOKEN', '');
store.commit('app/SET_USERNAME', '');
next();
} else {
//获取用户角色
//动态分配路由权限
next();
}
/**
* 1. to = /console 触发beforeEach,检测到token存在,next() --> 重定向到index
* 2. to = /index 触发beforeEach,检测到token存在,next() --> 进入控制台首页
*/
//路由动态添加,分配菜单,每个角色分配不同菜单
console.log("存在");
}else{
// next('/login'); //发生路由指向变化的情况下,会触发beforeEach,又会检测toKen存不存在,造成死循环 -- 解决方法:使用白名单!
console.log("不存在");
if (whiteRouter.indexOf(to.path) !== -1) { //当to.path == '/login' 的时候,存在,执行next(),跳到login页面,不触发beforeEach
next(); //指向(进入)to钩子--进入下一个页面,to.path == '/login'
}else{
next('/login'); //发生路由指向变化,触发beforeEach ---> to.path == '/login'
}
/**
* 解析:
* 1.直接进入 index 的时候,参数to被改变成了 "/index" ,触发路由指向,就会跑beforeEach(第一次)
* 2.再一次 next 指向了login, 再次发生路由指向,再跑beforeEach (第二次), 参数的to被改变成了 "/login"
* 3.白名单判断存在,则直接执行next(),因为没有参数,所以不会再跑beforeEach。
*/
}
})
router目录下的index.js
核心代码演示:
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
//引入布局组件
import Layout from '@/views/Layout';
const routes = [
{
path: "/",
redirect: "login",
hidden:true,
meta: {
name: "主页"
}
},
{
path: "/login",
name: "Login",
hidden:true,
meta: {
name: "登录"
},
component:() => import("../views/Login/index.vue")
},
/**
* 控制台
*/
{
path: "/console",
name: "Console",
redirect: "index",
meta: {
name: "控制台",
icon: "console"
},
component: Layout,
children: [
{
path: "/index",
name: "Index",
meta: {
name: "首页"
},
component: () => import("../views/Console/index.vue")
}
]
},
/**
* 信息管理
*/
{
path: "/info",
name: "Info",
meta: {
name: "信息管理",
icon: "info"
},
component: Layout,
children: [
{
path: "/infoIndex",
name: "InfoIndex",
meta: {
name: "信息列表"
},
component: () => import("../views/Info/index.vue")
},
{
path: "/infoCategory",
name: "InfoCategory",
meta: {
name: "信息分类"
},
component: () => import("../views/Info/category.vue")
}
]
},
/**
* 用户管理
*/
{
path: "/user",
name: "User",
meta: {
name: "用户管理",
icon: "user"
},
component: Layout,
children: [
{
path: "/userIndex",
name: "UserIndex",
meta: {
name: "用户列表"
},
component: () => import("../views/User/index.vue")
}
]
}
];
const router = new VueRouter({
routes
});
export default router;
Store下的index.js
核心代码演示:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
import app from "./modules/app.js"
import login from "./modules/login.js"
import common from "./modules/common.js"
export default new Vuex.Store({
modules: {
app,
login,
common
}
});
Store下的modules下的app.js(common.js和login.js省略)
核心代码演示:
import { Login } from "@/api/login";
import { setToKen, removeToKen, removeUserName, setUserName, getUserName } from '@/utils/app';
const state = { //没有做属性计算的情况下,直接用state可搞定
isCollapse: JSON.parse(sessionStorage.getItem('isCollapse')) || false, //JSON.parse:字符串转化为对象 1.优先去拿浏览器存储的值,如果取不到则去 ==> || false
// isCollapse: JSON.parse(localStorage.getItem('isCollapse')) || false
// isCollapse: JSON.parse(Cookie.get('isCollapse')) || false
to_ken: '',
username: getUserName() || '' //调用方法后,有数据,但是在Vuex中,页面刷新,数据会丢失,所以用cookie存储到的数据为初始数据,有则用cookie存的数据,没有则为''
}
const getters = { //computed 有做属性计算的情况下,用getters
isCollapse: state => state.isCollapse
}
const mutations = { //必须的 同步 没有回调处理事情
SET_COLLAPSE(state) {
state.isCollapse = !state.isCollapse;
//html5本地存储
sessionStorage.setItem('isCollapse', JSON.stringify(state.isCollapse)); //JSON.stringify 转化为字符串类型
// localStorage.setItem('isCollapse', JSON.stringify(state.isCollapse)); //JSON.stringify 转化为字符串类型
//cookie存储
// Cookie.set('isCollapse', JSON.stringify(state.isCollapse));
},
SET_TOKEN(state, value) {
state.to_ken = value
},
SET_USERNAME(state, value) {
state.username = value
}
}
const actions = { //可以回调处理事情
// setMenuStatus({ state, commit }, data) {
/**
* console.log(content)
* content.state
* content.getters
* content.commit
* content.rootGetters
*
* setMenuStatus(content, data) //第一种写法
* setMenuStatus({ state,getters,commit,rootGetters }, data) //对象结构的写法
*/
// commit('SET_COLLAPSE') -->同步: 通过actions定义一个方法,然后调用mutations里面的一些东西
// }
login({ commit }, requestData) {
//异步,请求接口返回数据后,接着去做别的事情
/**
* 接口A,接口B
* B接口需要A接口的参数
*/
return new Promise((resolve, reject) => { //异步: 可以通过promise,调用一个接口,成功时返回成功状态,失败时返回失败时的状态,再去调用的地方处理相应的事情
//接口
Login(requestData).then((response) => {
//toKen、username 需要存储起来
let data = response.data.data;
//普通的方式--login(content, requestData)
// content.commit('SET_TOKEN',data.token);
// content.commit('SET_USERNAME', data.username);
//解构的方式
commit('SET_TOKEN', data.token);
commit('SET_USERNAME', data.username);
setToKen(data.token);
setUserName(data.username);
resolve(response)
}).catch(error => {
reject(error)
})
})
},
exit({ commit }){
return new Promise((resolve, reject) => {
removeToKen();
removeUserName();
commit('SET_TOKEN', '');
commit('SET_USERNAME', '');
resolve();
})
}
}
export default {
namespaced: true, //开启命名空间 --解决不同模块命名冲突的问题
state,
getters,
mutations,
actions
};
utils目录下的app.js
核心代码演示:
import cookie from "cookie_js";
const adminToKen = "admin_toKen";
const usernameKey = "username";
export function getToKen(){
return cookie.get(adminToKen);
}
export function setToKen(toKen){
return cookie.set(adminToKen, toKen);
}
export function removeToKen(){
return cookie.remove(adminToKen);
}
export function setUserName(value) {
return cookie.set(usernameKey,value);
}
export function getUserName() {
return cookie.get(usernameKey);
}
export function removeUserName() {
return cookie.remove(usernameKey);
}