
在 Vue Router 中,嵌套路由可以通过在路由配置中定义 children 属性来实现。例如,以下是一个简单的嵌套路由配置:
import { createRouter, createWebHistory } from 'vue-router'; const routes = [ { path: '/', component: () => import('./views/Home.vue'), }, { path: '/dashboard', component: () => import('./views/Dashboard.vue'), children: [ { path: 'profile', component: () => import('./views/Profile.vue'), }, { path: 'settings', component: () => import('./views/Settings.vue'), }, ], }, ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router;
在这个例子中,/dashboard 是父路由,/dashboard/profile 和 /dashboard/settings 是子路由。
在父组件中,可以通过 来渲染子路由的组件:
<template> <el-menu :default-active="$route.path" router> <el-menu-item index="/home">首页</el-menu-item> <el-menu-item index="/users">用户管理</el-menu-item> <el-sub-menu index="/dashboard"> <template #title>仪表盘</template> <el-menu-item index="/dashboard/profile">个人资料</el-menu-item> <el-menu-item index="/dashboard/settings">设置</el-menu-item> </el-sub-menu> </el-menu> </template>
Element Plus 的 Menu 组件支持多种用法,包括水平菜单、垂直菜单、折叠菜单等。以下是一些基本用法:
<template> <el-menu :default-active="$route.path" router> <el-menu-item index="/home">首页</el-menu-item> <el-menu-item index="/users">用户管理</el-menu-item> <el-sub-menu index="/dashboard"> <template #title>仪表盘</template> <el-menu-item index="/dashboard/profile">个人资料</el-menu-item> <el-menu-item index="/dashboard/settings">设置</el-menu-item> </el-sub-menu> </el-menu> </template>
在这个例子中,el-menu 的 router 属性用于激活当前路由对应的菜单项。
水平菜单可以通过设置 mode=“horizontal” 来实现:
<template> <el-menu mode="horizontal" :default-active="$route.path" router> <el-menu-item index="/home">首页</el-menu-item> <el-menu-item index="/users">用户管理</el-menu-item> <el-sub-menu index="/dashboard"> <template #title>仪表盘</template> <el-menu-item index="/dashboard/profile">个人资料</el-menu-item> <el-menu-item index="/dashboard/settings">设置</el-menu-item> </el-sub-menu> </el-menu> </template>
可以通过动态绑定数据来生成菜单项。例如,从后端获取菜单数据并渲染:
<template> <el-menu :default-active="$route.path" router> <template v-for="item in menuData" :key="item.index"> <el-menu-item v-if="!item.children" :index="item.index"> {{ item.label }} </el-menu-item> <el-sub-menu v-else :index="item.index"> <template #title>{{ item.label }}</template> <el-menu-item v-for="child in item.children" :key="child.index" :index="child.index"> {{ child.label }} </el-menu-item> </el-sub-menu> </template> </el-menu> </template> <script setup> import { ref } from 'vue'; const menuData = ref([ { index: '/home', label: '首页' }, { index: '/users', label: '用户管理' }, { index: '/dashboard', label: '仪表盘', children: [ { index: '/dashboard/profile', label: '个人资料' }, { index: '/dashboard/settings', label: '设置' }, ], }, ]); </script>
在这个例子中,menuData 是一个动态生成的菜单数据数组。
当与 Vue Router 结合使用时,可以通过 router 属性激活当前路由对应的菜单项。例如:
<template> <el-menu :default-active="$route.path" router> <el-menu-item index="/home">首页</el-menu-item> <el-menu-item index="/users">用户管理</el-menu-item> <el-sub-menu index="/dashboard"> <template #title>仪表盘</template> <el-menu-item index="/dashboard/profile">个人资料</el-menu-item> <el-menu-item index="/dashboard/settings">设置</el-menu-item> </el-sub-menu> </el-menu> </template>
在这个例子中,el-menu 的 router 属性会根据当前路由路径($route.path)自动激活对应的菜单项。
Element Plus 的 Menu 组件提供了多种事件,例如 select、open 和 close。可以通过这些事件来处理菜单的交互逻辑。例如:
<template> <el-menu :default-active="$route.path" router @select="handleSelect"> <el-menu-item index="/home">首页</el-menu-item> <el-menu-item index="/users">用户管理</el-menu-item> <el-sub-menu index="/dashboard"> <template #title>仪表盘</template> <el-menu-item index="/dashboard/profile">个人资料</el-menu-item> <el-menu-item index="/dashboard/settings">设置</el-menu-item> </el-sub-menu> </el-menu> </template> <script setup> import { ref } from 'vue'; const handleSelect = (index) => { console.log(`Selected menu: ${index}`); }; </script>
在这个例子中,handleSelect 方法会在菜单项被选中时触发。
在实际应用中,通常需要根据用户的权限动态显示菜单项。可以通过在路由配置中添加权限属性,并在菜单渲染时进行过滤。例如:
const routes = [ { path: '/home', component: () => import('./views/Home.vue'), meta: { requiresAuth: false }, }, { path: '/users', component: () => import('./views/Users.vue'), meta: { requiresAuth: true }, }, { path: '/dashboard', component: () => import('./views/Dashboard.vue'), children: [ { path: 'profile', component: () => import('./views/Profile.vue'), meta: { requiresAuth: true }, }, { path: 'settings', component: () => import('./views/Settings.vue'), meta: { requiresAuth: true }, }, ], }, ];
然后在菜单渲染时,根据用户权限过滤菜单项:
<template> <el-menu :default-active="$route.path" router> <template v-for="item in filteredMenuData" :key="item.index"> <el-menu-item v-if="!item.children" :index="item.index"> {{ item.label }} </el-menu-item> <el-sub-menu v-else :index="item.index"> <template #title>{{ item.label }}</template> <el-menu-item v-for="child in item.children" :key="child.index" :index="child.index"> {{ child.label }} </el-menu-item> </el-sub-menu> </template> </el-menu> </template> <script setup> import { ref, computed } from 'vue'; import { useStore } from 'vuex'; const store = useStore(); const menuData = ref([ { index: '/home', label: '首页', meta: { requiresAuth: false } }, { index: '/users', label: '用户管理', meta: { requiresAuth: true } }, { index: '/dashboard', label: '仪表盘', children: [ { index: '/dashboard/profile', label: '个人资料', meta: { requiresAuth: true } }, { index: '/dashboard/settings', label: '设置', meta: { requiresAuth: true } }, ], }, ]); const filteredMenuData = computed(() => { return menuData.value.filter((item) => { if (!item.children) { return !item.meta.requiresAuth || store.state.isAuthenticated; } else { item.children = item.children.filter((child) => { return !child.meta.requiresAuth || store.state.isAuthenticated; }); return item.children.length > 0; } }); }); </script>
在这个例子中,filteredMenuData 是一个计算属性,根据用户的认证状态(store.state.isAuthenticated)动态过滤菜单项。
在某些情况下,菜单数据可能需要从后端动态加载。可以通过异步请求获取菜单数据,并在获取完成后渲染菜单。例如:
<template> <el-menu :default-active="$route.path" router v-if="menuData.length > 0"> <template v-for="item in menuData" :key="item.index"> <el-menu-item v-if="!item.children" :index="item.index"> {{ item.label }} </el-menu-item> <el-sub-menu v-else :index="item.index"> <template #title>{{ item.label }}</template> <el-menu-item v-for="child in item.children" :key="child.index" :index="child.index"> {{ child.label }} </el-menu-item> </el-sub-menu> </template> </el-menu> </template> <script setup> import { ref, onMounted } from 'vue'; import axios from 'axios'; const menuData = ref([]); onMounted(async () => { try { const response = await axios.get('/api/menu'); menuData.value = response.data; } catch (error) { console.error('Failed to load menu data:', error); } }); </script>
在这个例子中,onMounted 生命周期钩子用于在组件挂载时从后端加载菜单数据。
在国际化应用中,菜单项的标题可能需要根据用户的语言偏好动态显示。可以通过 Vue I18n 来实现菜单的国际化。例如:
<template> <el-menu :default-active="$route.path" router> <template v-for="item in menuData" :key="item.index"> <el-menu-item v-if="!item.children" :index="item.index"> {{ $t(item.label) }} </el-menu-item> <el-sub-menu v-else :index="item.index"> <template #title>{{ $t(item.label) }}</template> <el-menu-item v-for="child in item.children" :key="child.index" :index="child.index"> {{ $t(child.label) }} </el-menu-item> </el-sub-menu> </template> </el-menu> </template> <script setup> import { ref } from 'vue'; import { useI18n } from 'vue-i18n'; const { t } = useI18n(); const menuData = ref([ { index: '/home', label: 'menu.home' }, { index: '/users', label: 'menu.users' }, { index: '/dashboard', label: 'menu.dashboard', children: [ { index: '/dashboard/profile', label: 'menu.profile' }, { index: '/dashboard/settings', label: 'menu.settings' }, ], }, ]); </script> <i18n> { "en": { "menu": { "home": "Home", "users": "Users", "dashboard": "Dashboard", "profile": "Profile", "settings": "Settings" } }, "zh": { "menu": { "home": "首页", "users": "用户管理", "dashboard": "仪表盘", "profile": "个人资料", "settings": "设置" } } } </i18n>
在这个例子中,$t 方法用于动态翻译菜单项的标题。
Element Plus 的 Menu 组件支持折叠和展开功能。可以通过设置 collapse 属性来控制菜单的折叠状态。例如:
<template> <div> <el-button @click="toggleCollapse">切换菜单</el-button> <el-menu :default-active="$route.path" router :collapse="isCollapsed"> <el-menu-item index="/home">首页</el-menu-item> <el-menu-item index="/users">用户管理</el-menu-item> <el-sub-menu index="/dashboard"> <template #title>仪表盘</template> <el-menu-item index="/dashboard/profile">个人资料</el-menu-item> <el-menu-item index="/dashboard/settings">设置</el-menu-item> </el-sub-menu> </el-menu> </div> </template> <script setup> import { ref } from 'vue'; const isCollapsed = ref(false); const toggleCollapse = () => { isCollapsed.value = !isCollapsed.value; }; </script>
在这个例子中,isCollapsed 是一个响应式变量,用于控制菜单的折叠状态。点击按钮时,toggleCollapse 方法会切换菜单的折叠状态。
可以通过自定义 CSS 来调整菜单的样式。例如:
.el-menu { background-color: #f5f7fa; border-right: none; } .el-menu-item { color: #333; } .el-menu-item.is-active { background-color: #409eff; color: #fff; } .el-sub-menu__title { color: #333; } .el-sub-menu__title:hover { background-color: #e6f7ff; }
在这个例子中,自定义了菜单的背景颜色、字体颜色和激活状态的样式。
以下是一个完整的示例,结合了嵌套路由、动态菜单、权限控制、国际化和折叠功能:
import { createRouter, createWebHistory } from 'vue-router'; const routes = [ { path: '/', component: () => import('./views/Home.vue'), meta: { requiresAuth: false }, }, { path: '/users', component: () => import('./views/Users.vue'), meta: { requiresAuth: true }, }, { path: '/dashboard', component: () => import('./views/Dashboard.vue'), children: [ { path: 'profile', component: () => import('./views/Profile.vue'), meta: { requiresAuth: true }, }, { path: 'settings', component: () => import('./views/Settings.vue'), meta: { requiresAuth: true }, }, ], meta: { requiresAuth: true }, }, ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router;
<template> <div> <el-button @click="toggleCollapse">切换菜单</el-button> <el-menu :default-active="$route.path" router :collapse="isCollapsed"> <template v-for="item in filteredMenuData" :key="item.index"> <el-menu-item v-if="!item.children" :index="item.index"> {{ $t(item.label) }} </el-menu-item> <el-sub-menu v-else :index="item.index"> <template #title>{{ $t(item.label) }}</template> <el-menu-item v-for="child in item.children" :key="child.index" :index="child.index"> {{ $t(child.label) }} </el-menu-item> </el-sub-menu> </template> </el-menu> </div> </template> <script setup> import { ref, computed } from 'vue'; import { useStore } from 'vuex'; import { useI18n } from 'vue-i18n'; const { t } = useI18n(); const store = useStore(); const menuData = ref([ { index: '/home', label: 'menu.home', meta: { requiresAuth: false } }, { index: '/users', label: 'menu.users', meta: { requiresAuth: true } }, { index: '/dashboard', label: 'menu.dashboard', children: [ { index: '/dashboard/profile', label: 'menu.profile', meta: { requiresAuth: true } }, { index: '/dashboard/settings', label: 'menu.settings', meta: { requiresAuth: true } }, ], meta: { requiresAuth: true }, }, ]); const isCollapsed = ref(false); const toggleCollapse = () => { isCollapsed.value = !isCollapsed.value; }; const filteredMenuData = computed(() => { return menuData.value.filter((item) => { if (!item.children) { return !item.meta.requiresAuth || store.state.isAuthenticated; } else { item.children = item.children.filter((child) => { return !child.meta.requiresAuth || store.state.isAuthenticated; }); return item.children.length > 0; } }); }); </script> <i18n> { "en": { "menu": { "home": "Home", "users": "Users", "dashboard": "Dashboard", "profile": "Profile", "settings": "Settings" } }, "zh": { "menu": { "home": "首页", "users": "用户管理", "dashboard": "仪表盘", "profile": "个人资料", "settings": "设置" } } } </i18n>
.el-menu { background-color: #f5f7fa; border-right: none; } .el-menu-item { color: #333; } .el-menu-item.is-active { background-color: #409eff; color: #fff; } .el-sub-menu__title { color: #333; } .el-sub-menu__title:hover { background-color: #e6f7ff; }
通过结合 Vue 嵌套路由和 Element Plus 的 Menu 组件,可以实现功能丰富且灵活的导航菜单。本文介绍了从基础用法到高级功能的多种场景,包括动态菜单、权限控制、国际化、折叠功能和自定义样式。这些功能可以根据实际需求灵活组合,以满足复杂应用的需求。
以上就是Vue嵌套路由的各种用法详解的详细内容,更多关于Vue嵌套路由用法的资料请关注本站其它相关文章!