欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Vue基础】路由守卫+白名单

程序员文章站 2022-02-28 06:20:34
...

路由守卫+白名单

目录:
【Vue基础】路由守卫+白名单
核心代码演示:

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
【Vue基础】路由守卫+白名单
核心代码演示:

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
【Vue基础】路由守卫+白名单
核心代码演示:

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省略)
【Vue基础】路由守卫+白名单
核心代码演示:

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
【Vue基础】路由守卫+白名单
核心代码演示:

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);
}
相关标签: Vue.js vue vue.js