vue3动态路由+页面加载进度条

本文介绍了在Vue3项目中如何实现动态路由,通过后端传递的数据进行路由渲染,并提到了使用`addRoute`方法的关键点。同时,作者建议结合vue-devtools扩展以监测路由的添加情况。

前言

这个月使用vue3来架构公司后端项目,刚好要弄动态路由,我这里就抛砖引玉一下

开始

ruoter - config.ts

import {RouteRecordRaw} from "vue-router";
import LayoutView from "@/layout/IndexLayoutView.vue";

const routesList: Array<RouteRecordRaw> = [
    {
        path: '/login',
        name: 'login',
        component: () => import(/* webpackChunkName: "login" */ '@/views/login/IndexLoginView.vue')
    },
    {
        path: '/',
        name: 'layout',
        component: LayoutView,
        redirect: '/home',
        children: [
            {
                path: '404',
                component: () => import(/* webpackChunkName: "test" */ '@/views/404.vue'),
                name: '404',
                meta: {
                    title: '404'
<think>我们正在处理关于Vue3动态路由加载的问题。根据用户需求,我们需要提供实现方法或最佳实践,并给出示例。参考提供的引用内容,我们可以总结出几种常见的实现方式:1.前端路由:通过文件结构动态生成路由(如使用import.meta.glob)2.后端路由:根据用户角色/权限从服务器获取路由信息,然后动态添加路由我们将重点放在动态路由加载的实现步骤上,包括:-路由动态添加(使用VueRouter的addRoute方法)-权限验证(根据用户角色过滤路由)-解决刷新白屏问题(在刷新时重新加载动态路由)同时,我们将结合引用内容提供代码示例。步骤:1.定义静态路由(如登录页、404页等)和动态路由(需要权限的路由)2.用户登录后,获取用户权限信息(角色或菜单列表)3.根据权限信息,过滤出用户有权访问的路由4.使用router.addRoute()动态添加路由5.路由信息保存到状态管理(如Pinia)或本地存储,以便刷新时重新加载6.在应用初始化时(如main.ts)或路由守卫中检查并加载动态路由示例代码将展示如何实现动态路由加载,包括路由定义、权限过滤、添加路由以及处理刷新问题。注意:引用[4]提供了较完整的思路,包括如何根据角色菜单生成路由表,以及解决刷新白屏问题(在Pinia加载后,路由加载前重新加载动态路由)。下面我们开始组织回答。</think>### Vue3 动态路由加载实现方法与最佳实践 在 Vue3 中实现动态路由加载主要涉及**路由权限控制**和**按需加载**两大核心,以下是具体实现方式和最佳实践: #### 一、核心实现步骤 1. **路由表拆分** ```typescript // router/index.ts import { createRouter, createWebHistory } from &#39;vue-router&#39; // 静态路由(无需权限) const constantRoutes = [ { path: &#39;/login&#39;, component: () => import(&#39;@/views/Login.vue&#39;) }, { path: &#39;/404&#39;, component: () => import(&#39;@/views/404.vue&#39;) } ] // 动态路由模板(需权限控制) const asyncRouteMap = [ { path: &#39;/dashboard&#39;, component: () => import(&#39;@/layout/DefaultLayout.vue&#39;), meta: { requiresAuth: true, role: &#39;admin&#39; } } ] ``` 2. **权限验证与路由过滤** ```typescript // utils/auth.ts export const filterRoutes = (userRole: string, routes: RouteRecordRaw[]) => { return routes.filter(route => { // 验证路由权限 const routeRoles = route.meta?.role || [] return routeRoles.includes(userRole) || routeRoles.length === 0 }) } ``` 3. **动态添加路由** ```vue // Login.vue <script setup> import { useRouter } from &#39;vue-router&#39; import { filterRoutes } from &#39;@/utils/auth&#39; const router = useRouter() const userRole = ref(&#39;editor&#39;) // 从API获取实际角色 const loadDynamicRoutes = async () => { const allowedRoutes = filterRoutes(userRole.value, asyncRouteMap) allowedRoutes.forEach(route => router.addRoute(route)) // 添加404兜底路由(必须最后添加) router.addRoute({ path: &#39;/:pathMatch(.*)&#39;, redirect: &#39;/404&#39; }) } </script> ``` #### 二、最佳实践方案 1. **路由持久化方案**(解决刷新白屏) ```typescript // stores/authStore.ts (Pinia) import { defineStore } from &#39;pinia&#39; import { filterRoutes } from &#39;@/utils/auth&#39; export const useAuthStore = defineStore(&#39;auth&#39;, { actions: { async initDynamicRoutes() { const userRole = localStorage.getItem(&#39;userRole&#39;) if (!userRole) return const routes = await fetchRoutesFromAPI() // 从API获取路由配置 const filtered = filterRoutes(userRole, routes) filtered.forEach(route => this.router.addRoute(route)) } } }) // main.ts import { createApp } from &#39;vue&#39; import { useAuthStore } from &#39;./stores/authStore&#39; app.use(router) const authStore = useAuthStore() authStore.initDynamicRoutes() // 初始化动态路由 ``` 2. **路由元信息规范** ```typescript declare module &#39;vue-router&#39; { interface RouteMeta { requiresAuth?: boolean roles?: string[] // 允许访问的角色 title?: string // 菜单标题 icon?: string // 菜单图标 } } ``` 3. **动态菜单生成** ```vue // Layout.vue <template> <el-menu :routes="dynamicMenus" /> </template> <script setup> import { computed } from &#39;vue&#39; import { useRouter } from &#39;vue-router&#39; const router = useRouter() const dynamicMenus = computed(() => router.getRoutes().filter(route => route.meta?.showInMenu && !route.meta?.hidden ) ) </script> ``` #### 三、关键问题解决方案 1. **路由重复添加** 使用标志位控制初始化次数: ```typescript let isRoutesLoaded = false const loadRoutes = () => { if (isRoutesLoaded) return // ...添加路由逻辑 isRoutesLoaded = true } ``` 2. **404页面配置** 动态路由需最后添加兜底路由: ```typescript router.addRoute({ path: &#39;/:pathMatch(.*)*&#39;, redirect: &#39;/404&#39; }) ``` 3. **路由加载状态管理** ```vue <template> <router-view v-if="isRoutesReady"/> <Loading v-else /> </template> <script setup> import { watch } from &#39;vue&#39; import { useAuthStore } from &#39;@/stores/auth&#39; const authStore = useAuthStore() const isRoutesReady = ref(false) watch(() => authStore.routesLoaded, (loaded) => { if (loaded) isRoutesReady.value = true }) </script> ``` #### 四、完整工作流程 ```mermaid graph TD A[用户登录] --> B[获取用户角色/权限] B --> C[过滤可用路由] C --> D[动态添加路由] D --> E[生成导航菜单] E --> F[路由跳转] F --> G{页面刷新?} G -->|是| H[从持久化存储读取权限] H --> C G -->|否| F ``` > **最佳实践建议**: > 1. 使用路由加载`() => import()`提升性能 > 2. 配合Pinia/Vuex管理路由状态 > 3. 服务端返回路由标识而非完整结构 > 4. 添加路由加载进度条优化体验 > 5. 开发环境保留静态路由便于调试[^4] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

An_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值