VUE篇之,动态路由鉴权

登录->获取token存储->获取路由信息,动态添加路由

1.路由

路由文件可分为常显路由,比如login,404页面

router.js

import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);

/* Layout */
import Layout from "@/layout";

export const constantRoutes = [
  {
    path: "/login",
    component: () => import("@/views/login/index"),
    hidden: true,
  },

  {
    path: "/404",
    component: () => import("@/views/404"),
    hidden: true,
  },

  {
    path: "/",
    component: Layout,
    redirect: "/dashboard",
    children: [
      {
        path: "dashboard",
        name: "Dashboard",
        component: () => import("@/views/dashboard/index"),
        meta: { title: "Dashboard", icon: "s-tools" },
      },
    ],
  },
];

const createRouter = () =>
  new Router({
    mode: "history", // require service support
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRoutes,
  });

const router = createRouter();

const originalPush = Router.prototype.push;
Router.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject)
    return originalPush.call(this, location, onResolve, onReject);
  return originalPush.call(this, location).catch((err) => err);
};

export function resetRouter() {
  const newRouter = createRouter();
  router.matcher = newRouter.matcher; // reset router
}

export default router;

2.权限路由js文件,permission.js

主要内容如下:

1.const hasToken = getToken();

这块就是一开始我们登录成功,存储在local stroage里面的token

2.  const hasGetRoleList = store.getters.roleList.length;

const getters = {
  roleList: state => state.user.roleList,
}
export default getters

这块是我们获取接口权限路由列表返回数据

3.const roles = await store.dispatch("user/getInfo");

这块是我们请求路由权限列表的接口

我这里没有走真实接口,直接mock了数据

import list from "@/routeMock/data";

const state = {
  roleList: [], // 用于获取到的权限数据
};

const mutations = {
  SET_ROLELIST: (state, payload) => {
    state.roleList = payload;
  },
};

const actions = {
  // 获取侧边栏权限列表
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      commit("SET_ROLELIST", list);
      resolve(list);
    });
  },

};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
};

 4.convertMenuFormat方法,这个方法是将后端返回的数据,转换为正常我们页面需要的route.js里面写的结构。主要注意点:1.父节点conponent为Layout的问题,2.子节点加载.vue文件路径的问题

 引入:import Layout from "@/layout";主界面代码结构如下:

import Layout from "@/layout";

//....中间省略转换过程

//核心内容是这边的转换

if (menu.type === 1) {

        // 目录

        converted.component = Layout;

        converted.redirect = menu.path;

      } else if (menu.type === 2) {

        // 菜单

        converted.component = () => import(`@/views${menu.path}.vue`);

      }

 5.动态添加路由到router对象中

 const routes = convertMenuFormat(roles);

          routes.forEach((item) => {

            router.options.routes.push(item);

            router.addRoute(item);

          });

          router.addRoute({ path: "*", redirect: "/404", hidden: true });

完整permission。js代码如下 

import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { getToken } from "@/utils/auth";
import { filterASyncRoutes ,convertMenuFormat} from "@/page-utils/formateRoutes";

NProgress.configure({ showSpinner: false });

const whiteList = ["/login"];

router.beforeEach(async (to, from, next) => {
  NProgress.start();

  document.title = to.meta.title || "vue Admin Template";

  const hasToken = getToken();
  console.log('hasToken:', hasToken);

  if (hasToken) {
    if (to.path === "/login") {
      next({ path: "/" });
      NProgress.done();
    } else {
      const hasGetRoleList = store.getters.roleList.length;
      console.log('hasGetRoleList:', hasGetRoleList);
      if (hasGetRoleList) {
        next();
      } else {
        try {
          // 获取权限列表
          const roles = await store.dispatch("user/getInfo");
          // 将获得的权限列表,组装成router需要的类型
          const routes = convertMenuFormat(roles);
          routes.forEach((item) => {
            router.options.routes.push(item);
            router.addRoute(item);
          });
          router.addRoute({ path: "*", redirect: "/404", hidden: true });
          next({ ...to, replace: true });
        } catch (error) {
          await store.dispatch("user/resetToken");
          Message.error({
            message: error || "Has Error",
          });
          console.log("error: ", error);
          next(`/login?redirect=${to.path}`);
          NProgress.done();
        }
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next();
    } else {
      next(`/login?redirect=${to.path}`);
      NProgress.done();
    }
  }
});


router.afterEach(() => {
  NProgress.done();
});

侧边栏使用代码如下:

 computed: {
    routes() {
      return this.$router.options.routes;
    },
    activeMenu() {
      const route = this.$route;
      const { meta, path } = route;
      if (meta.activeMenu) {
        return meta.activeMenu;
      }
      return path;
    },
  },

 路由拼接数据结构内容:

 

Vue 路由守卫是一种机制,用于在用户路由切换时对其进行监控和控制。路由是一种安全机制,用于验证用户是否有限访问某个特定的路由或页面。 在 Vue 中,我们可以使用路由守卫来实现路由路由守卫有三种类型:全局前置守卫、路由独享守卫和组件内的守卫。 全局前置守卫通过在创建 Vue Router 实例时添加 `beforeEach` 方法来实现。该方法接受一个回调函数,在每次路由切换前被触发。我们可以在回调函数中进行限验证,例如判断用户是否登录以及是否有限访问该路由。如果用户没有限,我们可以通过 `next(false)` 或者 `next('/login')` 来中断路由导航或者跳转到登录页面。 路由独享守卫可以在路由配置中单独为某个路由添加 `beforeEnter` 方法来实现。该方法与全局前置守卫类似,可以在其中进行限验证。 组件内的守卫包括 `beforeRouteEnter`、`beforeRouteUpdate` 和 `beforeRouteLeave`。这些守卫可以在组件内部使用,用于对组件内的路由进行验证和处理。例如,在 `beforeRouteEnter` 守卫中,我们可以通过回调函数的参数 `next` 来控制路由导航,判断用户是否有限访问该路由。 使用路由守卫和路由可以有效地保护应用程序的安全性。通过在路由切换时进行限验证,可以防止未授的用户访问受限页面,并且可以根据需求进行灵活的限控制。这是一个非常重要的概念,特别是在需要保护用户隐私和敏感数据的应用程序中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值