在 Vue 3 项目中,Element Plus 的导航栏组件(el-menu
)与 Vue Router 结合使用,可以实现页面间的无缝导航。以下是具体实现方法:
确保已安装 Vue Router:
yarn add vue-router@4 # Vue 3 需要使用 v4 版本
创建路由配置文件 src/router/index.js
:
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue')
},
{
path: '/products',
name: 'Products',
component: () => import('../views/Products.vue')
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在 el-menu
中直接使用 router-link
组件作为菜单项,通过 index
属性绑定路由路径:
<template>
<el-menu
router <!-- 启用路由模式 -->
:default-active="activePath"
class="el-menu-demo"
mode="horizontal"
>
<el-menu-item index="/">首页</el-menu-item>
<el-menu-item index="/products">产品中心</el-menu-item>
<el-menu-item index="/about">关于我们</el-menu-item>
</el-menu>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// 获取当前路由路径作为激活状态
const activePath = computed(() => route.path)
</script>
从路由配置中自动生成导航菜单,避免手动维护重复代码:
<template>
<el-menu router :default-active="activePath" mode="horizontal">
<el-menu-item
v-for="route in routes"
:key="route.path"
:index="route.path"
>
{{ route.name }}
</el-menu-item>
</el-menu>
</template>
<script setup>
import { useRouter, useRoute } from 'vue-router'
import routes from '@/router' // 导入路由配置
const router = useRouter()
const route = useRoute()
// 过滤出需要在导航栏显示的路由
const routes = computed(() =>
router.options.routes.filter(route => !route.hidden)
)
// 当前激活路径
const activePath = computed(() => route.path)
</script>
对于嵌套路由,使用 el-sub-menu
组件:
<template>
<el-menu router :default-active="activePath" mode="horizontal">
<el-menu-item index="/">首页</el-menu-item>
<el-sub-menu index="products">
<template #title>产品中心</template>
<el-menu-item index="/products/list">产品列表</el-menu-item>
<el-menu-item index="/products/detail">产品详情</el-menu-item>
</el-sub-menu>
<el-menu-item index="/about">关于我们</el-menu-item>
</el-menu>
</template>
使用
watch
监听路由变化,实现导航栏与路由状态的同步:
<script setup>
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const activePath = ref(route.path)
// 监听路由变化,更新激活状态
watch(() => route.path, (newPath) => {
activePath.value = newPath
})
</script>
在路由导航守卫中处理权限验证或导航动画:
// router/index.js
router.beforeEach((to, from, next) => {
// 权限验证
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login')
} else {
next()
}
})
结合 Vue Router 和 Element Plus 实现一个响应式导航栏,包含移动端适配:
<template>
<div class="header">
<div class="logo">企业Logo</div>
<!-- 桌面端导航 -->
<el-menu
router
:default-active="activePath"
mode="horizontal"
class="desktop-menu"
>
<el-menu-item index="/">首页</el-menu-item>
<el-sub-menu index="products">
<template #title>产品中心</template>
<el-menu-item index="/products/list">产品列表</el-menu-item>
<el-menu-item index="/products/detail">产品详情</el-menu-item>
</el-sub-menu>
<el-menu-item index="/about">关于我们</el-menu-item>
<el-menu-item index="/contact">联系我们</el-menu-item>
</el-menu>
<!-- 移动端导航触发器 -->
<el-button
v-if="isMobile"
type="text"
@click="showMobileMenu = true"
>
<el-icon><Bars /></el-icon>
</el-button>
<!-- 移动端导航抽屉 -->
<el-drawer
v-model="showMobileMenu"
direction="rtl"
size="200px"
>
<el-menu
router
:default-active="activePath"
mode="vertical"
class="mobile-menu"
>
<el-menu-item index="/">首页</el-menu-item>
<el-sub-menu index="products">
<template #title>产品中心</template>
<el-menu-item index="/products/list">产品列表</el-menu-item>
<el-menu-item index="/products/detail">产品详情</el-menu-item>
</el-sub-menu>
<el-menu-item index="/about">关于我们</el-menu-item>
<el-menu-item index="/contact">联系我们</el-menu-item>
</el-menu>
</el-drawer>
</div>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import { Bars } from '@element-plus/icons-vue'
const route = useRoute()
const activePath = ref(route.path)
const showMobileMenu = ref(false)
const isMobile = ref(window.innerWidth < 768)
// 监听路由变化
watch(() => route.path, (newPath) => {
activePath.value = newPath
// 路由切换后关闭移动端菜单
if (showMobileMenu.value) {
showMobileMenu.value = false
}
})
// 监听窗口大小变化,处理响应式
const handleResize = () => {
isMobile.value = window.innerWidth < 768
}
onMounted(() => {
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
})
</script>
<style scoped>
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
height: 60px;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.logo {
font-size: 20px;
font-weight: bold;
}
.desktop-menu {
border-bottom: none;
}
.mobile-menu {
border-right: none;
}
/* 移动端隐藏桌面菜单 */
@media (max-width: 768px) {
.desktop-menu {
display: none;
}
}
/* 桌面端隐藏移动端菜单触发器 */
@media (min-width: 769px) {
.mobile-menu-trigger {
display: none;
}
}
</style>
-
router
属性
在 el-menu
中添加 router
属性,启用路由模式,菜单项的 index
将被视为路由路径。
-
动态激活状态
通过 :default-active="activePath"
绑定当前路由路径,实现导航栏高亮。
-
导航守卫
利用 Vue Router 的导航守卫(beforeEach
、afterEach
)处理权限验证、页面加载动画等。
-
响应式设计
结合 CSS 媒体查询和 JavaScript 监听窗口大小变化,实现移动端和桌面端不同的导航布局。
通过以上方式,你可以实现一个功能完善、交互流畅的企业级导航系统,同时保持代码的可维护性和可扩展性。