vue动态路由的实现方式

思路:本地写死路由,根据登录角色添加不同的动态路由

  • 路由文件:分为静态路由和动态路由
  • 登录成功,判断角色,addRoute添加动态路由,并且存储路由数组
  • 根据路由数组生成菜单栏

方法一:

  • 直接获取路由this.$router.options.routes,但是addRoute添加的动态路由使用该方法获取不到,options里边没有
  • 解决方法:在addRoute添加动态路由前,手动拼接静态和动态路由,赋值给options。this.$router.options.routes = [全路由数组],但是页面手动刷新的时候还是会丢失动态添加的路由

方法二:

  • 在addRoutes添加动态路由前,将拼接路由存入vuex中,然后使用vuex中的路由生成菜单栏;
  • 但是刷新的时候vuex会丢失路由,可以吧vuex存本地,每次刷新重新在vuex中获取路由

bug:

  1. 本次采用的方法二
  2. 动态添加的路由,刷新后点击跳转404页面,{path:’*’,redirect: ‘/404’…}不能放在静态路由里,否则刷新的时候即便获取到了异步路由数据也会直接跳转到404,解决方法应该将该路由放在动态路由里
  3. 采用方法二,登录后addRoutes异步添加的路由可以正常跳转。但是浏览器刷新之后会路由会丢失,页面跳转不过去,在router.beforeEach()方法中发现刷新时to.name为null。解决方法:在路由守卫里判断如果to.name==null,重新添加一遍路由
  4. 使用addRoutes报错Error: [vue-router] “path“ is required in a route configuration.因为这个api已经废弃,新的api是addRoute(参数为对象,而不是数组),所以需要循环添加
    4.在路由守卫里判断如果to.name==null,重新添加一遍路由,之后next()。 vue-router报错Error: Navigation cancelled from “/course“ to “/user“ with a new navigation. 原因全局导航守卫中出现了页面跳转到了一个页面之后又重定向到了另一个界面,
    修改 next({ …to, replace: true })

router.js

import Vue from "vue";
import VueRouter from "vue-router";
import Layout from "@/layout/index";
import store from "../store/index";
Vue.use(VueRouter);

export const constantRoutes = [
  {
    
    
    path: "/",
    redirect: "/home",
    component: Layout,
    meta: {
    
    
      title: "首页",
      icon: "el-icon-s-home",
      path: "/home",
    },
    children: [
      {
    
    
        path: "home",
        name: "home",
        component: () => import("../views/Home"),
      },
    ],
  },
  {
    
    
    path: "/device",
    redirect: "/device/list",
    component: Layout,
    meta: {
    
    
      title: "设备管理",
      icon: "el-icon-mobile",
    },
    children: [
      {
    
    
        path: "list",
        name: "diviceList",
        component: () => import("../views/device/list"),
        meta: {
    
    
          title: "网关列表",
          path: "/device/list",
        },
      },
      {
    
    
        path: "log",
        name: "diviceLog",
        component: () => import("../views/device/log"),
        meta: {
    
    
          title: "监控日志",
          path: "/device/log",
        },
      },
      {
    
    
        path: "warn",
        name: "diviceWarn",
        component: () => import("../views/device/warn"),
        meta: {
    
    
          title: "预警设置",
          path: "/device/warn",
        },
      },
    ],
  },
  {
    
    
    path: "/login",
    component: () => import("../views/login/login"),
    hidden: true,
  },
  {
    
    
    path: "/404",
    component: () => import("../views/404"),
    hidden: true,
  },
];
// 在登陆成功时,获取用户身份,动态添加路由
// this.$router.addRoute(asyncRoutes)
export const asyncRoutes = [
  {
    
    
    path: "/user",
    component: Layout,
    meta: {
    
    
      title: "用户管理",
      icon: "el-icon-setting",
      path: "/user/list",
    },
    children: [
      {
    
    
        path: "list",
        name: "userList",
        component: () => import("../views/user/list"),
      },
    ],
  },
  {
    
    
    path: "*",
    redirect: "/404",
    hidden: true,
  },
];
const router = new VueRouter({
    
    
  routes: constantRoutes,
});

router.beforeEach((to, from, next) => {
    
    
  if (to.path == "/login") return next();
  const token = localStorage.getItem("token");
  if (!token) return next("/login");
  // 解决页面刷新,动态路由丢失,所以重新add
  if (!to.name && store.state.userInfo.role == 0) {
    
    
    asyncRoutes.forEach((item) => {
    
    
      router.addRoute(item);
    });
    next({
    
     ...to, replace: true });
  } else {
    
    
    next();
  }
});
export default router;


vuex

import Vue from "vue";
import Vuex from "vuex";
import {
    
     constantRoutes, asyncRoutes } from "../router/index";
import router from "../router/index";
Vue.use(Vuex);

export default new Vuex.Store({
    
    
  state: {
    
    
    open: true, //菜单栏是否展开
    userInfo: JSON.parse(localStorage.getItem("userInfo") || "{}"),
    routes: localStorage.getItem("routes")
      ? JSON.parse(localStorage.getItem("routes"))
      : constantRoutes,
  },
  mutations: {
    
    
    // 菜单的关闭
    changeOpen(state, data) {
    
    
      state.open = data;
    },
    // 存储用户信息
    // "userId":"afsdkasdfadsfds",
    //  "token":"xxxxxxxxxxxxxxxxxxxxxxx",
    //  "role":"1"   0:超级管理员 1:管理员
    saveUserInfo(state, data) {
    
    
      state.userInfo = data;
      localStorage.setItem("token", data.token);
      localStorage.setItem("userInfo", JSON.stringify(data));
    },
    // 动态路由,根据这个路由生成菜单
    saveRoutes(state) {
    
    
      if (state.userInfo.role == 0) {
    
    
        console.log(asyncRoutes);
        asyncRoutes.forEach((item) => {
    
    
          router.addRoute(item);
        });
        state.routes = constantRoutes.concat(asyncRoutes);
      } else {
    
    
        state.routes = constantRoutes;
      }
      localStorage.setItem("routes", JSON.stringify(state.routes));
    },
  },
  actions: {
    
    },
  modules: {
    
    },
});

login

			this.$axios
            .post("/supportOldMan/sysUser/loginCheck", {
    
    
              userName: this.ruleForm.name,
              passWord: this.ruleForm.pass,
            })
            .then((data) => {
    
    
              this.$store.commit("saveUserInfo", data);
              // 根据userInfo的身份信息保存路由路由
              this.$store.commit("saveRoutes");
              this.$message.success("登录成功");
              setTimeout(() => {
    
    
                this.$router.replace("/home");
              }, 1000);
            });

猜你喜欢

转载自blog.csdn.net/weixin_43848576/article/details/120067285