Loading

Vue3根据菜单动态生成路由

前言

学无止境,无止境学。大家好,我是张大鹏,之前在抖音有5万多粉丝,不过现在不拍视频,专心写公众号了。笔者目前是高级Python工程师,之前是全栈工程师,主要擅长Golang和Python开发,对于Java,Vue,React也有一些研究。工作之余,喜欢学习和分享,希望能够通过此公众号,将自己学到的东西分享给大家,和大家一起交流,一起成长,一起进步。

 

根据菜单动态添加路由

之前咱们的路由是在router里面直接写死的,这样是不太合理的。因为每个用户都有自己不同的菜单,我们应该根据不同的用户菜单,生成不同的路由。根据用户信息中的菜单列表,动态的生成该用户拥有的路由。

修改路由器:src/core/router/index.js

import {createRouter, createWebHashHistory} from "vue-router"

// 引入页面
import Layout from "../../pages/layout/index.vue"
import NotFound from "../../pages/404.vue"
import Login from "../../pages/login.vue"
import Index from "../../pages/index.vue"

// 静态路由数组
const routes = [
    // 配置单个路由
    {
        path: "/",
        name: "Layout",
        component: Layout,
    },
    // 登录页面
    {
        path: "/login",
        name: "Login",
        component: Login,
        meta: {
            title: "登录"
        }
    },
    // 所有不存在的路由都走404
    {
        path: "/:pathMatch(.*)*",
        name: "NotFound",
        component: NotFound,
    },
]

// 动态路由,用于匹配菜单,动态添加路由
const dynamicRoutes = [
    {
        path: "/index",
        name: "Index",
        component: Index,
        meta: {
            title: "首页",
        }
    },
    {
        path: "/analysis",
        name: "Analysis",
        component: Index,
        meta: {
            level: 1, // 是一级路由
            title: "可视化大屏",
        }
    },
]

// 创建路由器,管理所有路由
export const router = createRouter({
    history: createWebHashHistory(),
    routes
})

// 动态添加路由的方法
export const addRoutes = (menus) => {
    // 是否有新的路由
    let hasNewRoute = false
    // 从动态路由中找菜单
    const findRoute = (menuArr) => {
        // 遍历每个菜单
        menuArr.forEach(menu => {
            // 从动态路由中找到和菜单的路径相同的路由
            let route = dynamicRoutes.find(route => route.path === menu.url_path)
            // 如果找到了,且没有注册过
            if (route && !router.hasRoute(route.name)) {
                if (route.meta && route.meta.level && route.meta.level === 1) {
                    // 添加一级路由
                    router.addRoute(route)
                } else {
                    // 添加子路由
                    router.addRoute("Layout", route)
                }
                hasNewRoute = true
            }
            // 如果还有嵌套路由
            if (menu.children && menu.children.length > 0) {
                findRoute(menu.children)
            }
        })
    }
    // 为菜单动态添加路由
    findRoute(menus)
    // 返回
    return hasNewRoute
}

 

修改路由拦截器,在用户访问页面之前,根据其菜单动态添加路由:src/router/permission.js

import {addRoutes, router} from "./index.js"
import {getToken} from "../utils/cookie.js";
import {hideFullLoading, showFullLoading, toast} from "../utils/message.js";
import store from "../store/index.js";

// 全局前置守卫
router.beforeEach(async (to, from, next) => {
    // 显示loading
    showFullLoading()

    // 获取token
    const token = getToken()
    // 还没有登录,且不是访问登录页面,跳转到登录页面
    if (!token && to.path !== "/login") {
        toast("请先登录", "warning")
        return next({path: "/login"})
    }
    // 防止重复登录:有token,且访问的是登录页面
    if (token && to.path === "/login") {
        toast("您已经登录过了", "warning")
        // 跳转到之前的页面或者首页
        return next({path: from.path || "/"})
    }
    // 判断是否有新的路由
    let hasNewRoute = false
    // 如果用户登录了,自动化获取用户信息,并存储在vuex中
    if (token) {
        let userData = await store.dispatch("actionGetUserInfo")
        // 动态添加路由
        hasNewRoute = addRoutes(userData.menus)
    }
    // 设置页面标题
    document.title = (to.meta.title || "") + "-企业级商城后台管理系统"
    // 放行
    hasNewRoute ? next(to.fullPath) : next()
})

// 全局后置守卫
router.afterEach((to, from) => hideFullLoading())

 

另外,在引入了router的地方,需要修改其对router的引入方式:

  • src/main.js

  • src/core/store/index.js

import {router} from "../router/index.js";
posted @ 2023-02-20 11:49  RuoVea  阅读(711)  评论(0编辑  收藏  举报