在 Vue3 + Vite 项目里,动态路由一般有 3 种常见场景

在 Vue3 + Vite 项目里,动态路由一般有 3 种常见场景,通常用的是 「后端返回菜单 → 前端动态生成路由」 这一套。

✅ 一、先理解什么是动态路由

动态路由 ≠ /user/:id 这种参数路由。

在后台系统里通常指:

👉 运行时动态 addRoute

登录后才加载页面

根据权限加载页面

后端控制菜单

例如:

{ "name": "WeakPlan", "path": "/plan/weak", "component": "plan/weak/index" }

前端收到后动态注册。

✅ 二、目录结构(推荐)

src

├── router

│ ├── index.ts # 路由入口

│ ├── dynamic.ts # 动态路由处理

│ └── modules

├── views

│ ├── plan

│ │ └── weak

│ │ └── index.vue

✅ 三、基础路由(固定路由)

先写不会变的页面:

// router/index.ts

import { createRouter, createWebHistory } from 'vue-router'

export const constantRoutes = [

{

path: '/login',

component: () => import('@/views/login/index.vue')

},

{

path: '/',

component: () => import('@/layout/index.vue'),

redirect: '/dashboard'

}

]

const router = createRouter({

history: createWebHistory(),

routes: constantRoutes

})

export default router

✅ 四、核心:动态加载 view(Vite 写法)

⚠️ Vite 不能用 webpack 的 require。

必须用:

⭐ import.meta.glob(重点)

// router/dynamic.ts

// 自动扫描 views 下所有页面

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

得到类似:

{

".../views/plan/weak/index.vue": () => import(...)

}

✅ 五、后端路由 → Vue Router 转换

示例后端数据

{

"path": "/plan/weak",

"name": "WeakPlan",

"component": "plan/weak/index"

}

转换函数

import router from './index'

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

export function loadAsyncRoutes(routes: any\[\]) {

routes.forEach(route => {

复制代码
const componentPath =
  `../views/${route.component}.vue`

route.component = modules[componentPath]

router.addRoute(route)

})

}

✅ 六、登录后动态注册(真正项目写法)

// login 成功后

const menuRoutes = await getUserMenus()

loadAsyncRoutes(menuRoutes)

✅ 七、刷新页面丢失路由(必须解决)

动态路由最大坑:

👉 F5 刷新后 addRoute 消失

解决方案:

在路由守卫里重新加载

let isLoaded = false

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

if (!isLoaded && token存在) {

复制代码
const routes = await getUserMenus()
loadAsyncRoutes(routes)

isLoaded = true

next({ ...to, replace: true })
return

}

next()

})

✅ 八、支持 Layout 嵌套路由(后台必备)

后端返回:

{

"path": "/plan",

"component": "Layout",

"children": [

{

"path": "weak",

"component": "plan/weak/index"

}

]

}

前端处理:

import Layout from '@/layout/index.vue'

if (route.component === 'Layout') {

route.component = Layout

}

相关推荐
lichenyang4536 小时前
Docker 学习笔记(一):为什么需要镜像、容器和仓库?
前端
kyriewen6 小时前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
IT_陈寒6 小时前
SpringBoot自动配置的坑,我的API突然就404了
前端·人工智能·后端
奇奇怪怪的7 小时前
Embedding 模型 10+ 横向评测
前端
陈广亮7 小时前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端
子兮曰7 小时前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
敲代码的鱼7 小时前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
子兮曰8 小时前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust
Hyyy9 小时前
Function Calling / Tool Use的原理和实现模式
前端·llm·ai编程