从零开始vue3+vite+ts+pinia+router4后台管理(3)-动态路由

从零开始vue3+vite+ts+pinia+router4后台管理(3)-动态路由

项目地址

项目git地址

我们在做项目中经常遇到有后端返回的文件路径(比如order/orderList),然后前端根据获取的路由数组动态加载路由,今天我们就看看怎么样实现的吧!本项目vue版本vue3 vue-router4 pinia Vite 完成的

实现思路

  1. 在路由钩子里面判断是否首次进入系统(permission.ts)

  2. init为true说明已经获取过路由,就直接放行,init为false则向后台请求用户路由

  3. 获取路由

  4. 解析路由,存储权限

  5. 使用router的api addRoute拼接路由

  6. 存储路由

  7. init改为true,路由初始化完成

  8. 放行路由

###1 引入vue-router 设置静态路由 登陆,首页等。。。

router/index.ts

typescript 复制代码
import {createRouter, createWebHistory} from 'vue-router'
import Layout from '@/layout/index.vue'
//constantRoutes 静态路由 登陆,首页等。。。
export const constantRoutes = [
    {
        path: '/',//默认首页
        redirect: '/dashboard',
        hidden: true,
    },
    {
        path: "/dashboard",
        name: 'Dashboard',
        meta: {
            title: '首页',
            icon: "House",
        },
        component: Layout
    },
    {
        path: "/login",
        name: "Login",
        meta: {
            title: '登录'
        },
        component: () => import('@/views/user/login/index.vue'),
        hidden: true
    },
    {
        path: '/:pathMatch(.*)*',// 此写法解决动态路由页面刷新的 warning 警告
        component: () => import('@/views/user/error-page/404.vue'),
        hidden: true
    },
]
//动态路由 asyncRoutes
export const asyncRoutes = []

const router = createRouter({
    history: createWebHistory(),// HTML5的history模式
    routes: constantRoutes
})

export default router

2 获取后端路由数组,动态挂载路由permission.ts

permission.ts入口权限判断ts 和mian.ts同一级

typescript 复制代码
import router from './router/index'
import { useUserStore } from '@/store/user'
import { usePermissionStore } from '@/store/permission'
import {getToken} from '@/utils/storage.ts'
import NProgress from 'nprogress'
import'nprogress/nprogress.css'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // 白名单
router.beforeEach(async (to) => {
    NProgress.start();
    document.title = `${to.meta.title} | vu3dny-admin`
    const hasToken = getToken('Access-Token')
    const userStore = useUserStore()
    const permissionStore = usePermissionStore()
    if (hasToken) {//判断token是否存在 存在即为已经登录
        if (to.path !== "/login") {
            if (userStore.init) { // 获取了动态路由 init一定true,就无需再次请求 直接放行
                return true
            }else {
                // init为false,一定没有获取动态路由,就跳转到获取动态路由的方法
                const result = await userStore.getInfo() //获取路由
                const accessRoutes = await permissionStore.generateRoutes(result.menus) 				//解析路由,存储路由
                // console.log(accessRoutes);
                // 动态挂载路由
                accessRoutes.forEach((route) => {
                    router.addRoute(route)
                })
                userStore.init = true//init改为true,路由初始化完成
                return { ...to, replace: true }// hack方法 确保addRoute已完成

            }
        }else {
            NProgress.done()
            return '/'
        }

    }else {
        // 白名单,直接放行
        if (whiteList.indexOf(to.path) > -1) return true
        // 非白名单,去登录
        else return '/login'
        NProgress.done()
    }
})
router.afterEach(() => {
    // finish progress bar
    NProgress.done()
})

3 递归解析路由 根据后端返回文件路径匹配路由

==import.meta.glob==的妙用:Vite是一个现代工具,你主要使用ES模块。而Vite用方便的工具扩展了全局import.meta 对象。例如,它添加了一个import.meta.glob 函数,允许你从路径中解析文件。比如后端返回的是oder/orderList 路由 需要前端匹配 你需要在views文件夹 新建一个order文件夹 然后文件夹新建一个orderList.vue

const modules = import.meta.glob('@/views/**/**.vue')

router的componentcomponent = modules[/src/views${e.url}]

当然 如果你用的是vue2 vueCli构建的vue项目 你可以用 require引入 import.meta.glob只适用于Vite

store/permission.ts 生成动态路由权限

typescript 复制代码
import {defineStore} from 'pinia'
import {constantRoutes} from '@/router'
import Layout from '@/layout/index.vue'
const modules = import.meta.glob('@/views/**/**.vue')
// console.log(modules);
export const filterAsyncRoutes = (routerList) => {
    //进行递归解析
    //routerList 后端获取的路由
    const res = []
    // console.log(testData);
    routerList.forEach(e => {
        // console.log(e.component);
        let e_new = {
            path: e.url,
            name: e.menuName,
            meta: {
                title: e.menuName,
                icon: e.icon
            },
             component: null

        }
        if (e.menuType === 'M') {
            e_new.component = Layout
        }else {
            // console.log("22222",e.url);
            e_new.component = modules[`/src/views${e.url}/index.vue`]
        }
        // console.log(e_new);
        if (e.children && e.children!=null) {
            const children = filterAsyncRoutes(e.children)
            // 保存权限
            e_new = { ...e_new, children: children }
        }

        res.push(e_new)
    })
    // console.vlog("111",res);
    return res
}

export const usePermissionStore = defineStore('permission', {
    id: 'permission', // id必填,且需要唯一
    state: () => {
        return {
            routes: [],//全部路由
            addRoutes: []//后端增加的路由
        }
    },
    actions: {
        generateRoutes(routes) {
            // console.log(routes);
            let routerList = JSON.parse(JSON.stringify(routes))
            // console.log(routerList);
            return new Promise((resolve) => {
                
                const accessedRoutes = filterAsyncRoutes(routerList)
                // console.log(accessedRoutes);
                this.addRoutes = accessedRoutes
                // console.log("111",accessedRoutes);
                this.routes = constantRoutes.concat(accessedRoutes)
                resolve(accessedRoutes)
            })

        }
    }
})
相关推荐
a栋栋栋4 小时前
apifox
java·前端·javascript
请叫我飞哥@5 小时前
HTML 标签页(Tabs)详细讲解
前端·html
Anlici5 小时前
React18与Vue3组件通信对比学习(详细!建议收藏!!🚀🚀)
前端·vue.js·react.js
m0_748251526 小时前
PDF在线预览实现:如何使用vue-pdf-embed实现前端PDF在线阅读
前端·vue.js·pdf
中生代技术6 小时前
3.从制定标准到持续监控:7个关键阶段提升App用户体验
大数据·运维·服务器·前端·ux
m0_748239336 小时前
从零开始:如何在.NET Core Web API中完美配置Swagger文档
前端·.netcore
m0_748232926 小时前
【前端】Node.js使用教程
前端·node.js·vim
hawleyHuo6 小时前
umi 能适配 taro组件?
前端·前端框架
web130933203987 小时前
[JAVA Web] 02_第二章 HTML&CSS
java·前端·html
黑客呀7 小时前
Go Web开发之Revel - 网页请求处理流程
开发语言·前端·web安全·golang·系统安全