菜单路由跳转:菜单事件传递
菜单的视觉渲染只是第一步,真正的核心在于点击菜单项后的路由跳转。Element Plus 的 el-menu 提供 select 事件,携带被选中菜单项的 index 值。我们需要将这个 index 映射回路由路径,然后通过 Vue Router 进行页面跳转。
el-menu 的 select 事件
// el-menu 的 select 事件签名
interface MenuSelectEvent {
(index: string, indexPath: string[], item: MenuItemClicked): void
}
typescript
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| index | string | 被选中菜单项的 index 值(即我们生成的 key) |
| indexPath | string | 从根到当前的 index 路径 |
| item | MenuItemClicked | 被点击的菜单项实例 |
事件传递链路
用户点击菜单项
→ el-menu 触发 select(index, indexPath)
→ Menu 组件 emit('select', index, indexPath)
→ DefaultLayout 接收 select 事件
→ 根据 index 查找对应的路由路径
→ router.push(path)
text
Menu 组件的事件定义
// menu.vue
const emit = defineEmits<{
select: [index: string, indexPath: string[]]
}>()
const handleSelect = (index: string, indexPath: string[]) => {
emit('select', index, indexPath)
}
typescript
模板绑定:
<el-menu @select="handleSelect">
vue
index 到路由路径的映射
由于 generateMenuKeys 生成的 index 是层级化的(如 1-2-3),需要在 useMenu 中维护一个映射表:
// use-menu.ts
const indexToPathMap = new Map<string, string>()
function generateMenuKeys(menus: AppRouteMenuItem[], level = 0) {
// ...生成 key 的同时建立映射
indexToPathMap.set(key, item.path)
}
function getPathByIndex(index: string): string {
return indexToPathMap.get(index) ?? '/'
}
typescript
在 DefaultLayout 中使用:
const handleMenuSelect = (index: string) => {
const path = getPathByIndex(index)
router.push(path)
}
typescript
路由跳转的注意事项
外部链接
如果菜单项的 path 是外部链接(以 http 开头),不应使用 router.push:
function handleMenuSelect(index: string) {
const path = getPathByIndex(index)
if (path.startsWith('http')) {
window.open(path, '_blank')
} else {
router.push(path)
}
}
typescript
当前路由重复跳转
点击当前已激活的菜单项时,Vue Router 会报重复导航警告:
if (router.currentRoute.value.path !== path) {
router.push(path)
}
typescript
路由守卫
路由跳转可能被导航守卫拦截(如未登录重定向到登录页)。菜单组件不需要处理这种情况——由路由守卫统一处理。
本节小结
- select 事件:
el-menu的select事件携带被选中菜单项的 index 值。 - 映射表:
indexToPathMap将生成的 index 映射回路由路径。 - 路由跳转:通过
router.push(path)跳转,外部链接使用window.open。 - 重复跳转:检查当前路由是否与目标路由相同,避免重复导航警告。
↑