Skip to content

动态路由是整个后台管理系统中最核心的部分,这里是来介绍一下动态路由是怎样实现的吧。

动态路由的实现

  1. 将各个模块的路由保存在一个单独的文件,如下:
typescript
export default {
  path: '/',
  name: 'Layout',
  component: () => import('@/layout/index.vue'),
  redirect: '/home',
  children: [
    {
      path: 'home',
      name: 'Home',
      component: () => import('@/views/home/index.vue'),
      meta: {
        title: '项目介绍',
        isShow: true,
      },
    },
    {
      path: 'user',
      name: 'User',
      component: () => import('@/views/user/index.vue'),
      meta: {
        title: '用户列表',
        isShow: true,
      },
    },
    {
      path: 'role',
      name: 'Role',
      component: () => import('@/views/role/index.vue'),
      meta: {
        title: '角色列表',
        isShow: true,
      },
    },
    {
      path: 'auth',
      name: 'Auth',
      component: () => import('@/views/auth/index.vue'),
      meta: {
        title: '权限列表',
        isShow: true,
      },
    },
  ],
}
typescript
export default {
  path: '/login',
  name: 'login',
  component: () => import('@/views/login/index.vue'),
  children: [],
}
  1. 使用vite提供的api动态加载所有的这些单独的路由文件
typescript
const modules: Record<string, any> = import.meta.glob('./modules/*.ts', {
  eager: true,
})
  1. 循环得到的modules,配置router
typescript
const routes: Array<RouteRecordRaw> = []
Object.keys(modules).forEach((key) => {
  const module = modules[key]
  routes.push(module.default)
})

最终得到的routes数据就是最终的路由配置对象,然后将这个配置对象传给路由对象。

typescript
const router = createRouter({
  history: createWebHashHistory(),
  routes,
})

动态路由渲染动态导航菜单

在后台管理系统中,路由是与导航菜单相辅相成的,接下来介绍一下导航菜单的渲染。具体步骤如下:

  1. 通过Vue提供的useRouter方法动态获取所有路由对象
  2. 利用Element Plus提供的el-menu组件遍历所有路由对象形成导航菜单

具体实现如下:

typescript
import { useRouter, useRoute } from 'vue'
const route = useRoute()
const router = useRouter()

const routes = router.getRoutes()
const menuList = routes.filter((route) => {
  return route.meta.isShow
})
vue
<el-menu
	:default-active="activePath"
	class="el-menu-vertical-demo"
	background-color="#545c64"
	router
>
	<template v-for="item in menuList" :key="item.name">
		<template v-if="!item.children">
			<el-menu-item :index="item.path">
				{{ item.meta!.title }}
			</el-menu-item>
		</template>
		<template v-else>
				<el-sub-menu :index="item.path">
						<template #title>
							<span>{{ item.meta?.title }}</span>
						</template>
					<template
						v-for="subItem in item.children"
						:key="subItem.path"
						>
						<el-menu-item :index="subItem.path">
							{{ subItem.meta?.title }}
						</el-menu-item>
					</template>
				</el-sub-menu>
			</template>
		</template>
</el-menu>