您的位置:首页 > 路由器知识路由器知识

2023超详细Vue3+Element-Plus路由菜单实战:从0到1搭建动态导航栏(小白也能看懂)

2026-05-03人已围观

2023超详细Vue3+Element-Plus路由菜单实战:从0到1搭建动态导航栏(小白也能看懂)

一、先看效果:3分钟搞懂我们要做什么

想象一下你去餐厅吃饭,一进门就看到墙上挂着菜单,想吃什么直接点,后厨就给你做什么。今天咱们要做的就是给网站做一个"点餐系统"——左侧是菜单(导航栏),点哪个菜(菜单选项),右边就显示对应的菜(页面内容)。这种"点啥出啥"的效果,在Vue里全靠路由和导航栏配合实现。

具体来说,就是左侧固定一个导航菜单,里面的选项会根据我们配置的路由自动生成,点击不同选项,右边区域就会显示不同的页面内容。整个界面就像个文件夹,左边是文件目录,右边是文件内容预览,是不是很好理解?

二、准备工作:这些"食材"得先备好

在开始做菜前,咱们得把锅碗瓢盆准备好。这里需要安装几个核心"工具":

1. Node.js:相当于咱们的灶台,没有它Vue项目跑不起来。建议安装v16.x以上版本,官网直接下载安装就行,一路下一步到底。

2. Vue CLI:这是Vue官方的"菜谱生成器",能帮我们快速搭好项目架子。安装命令很简单,打开命令行输入:`npm install -g @vue/cli`

3. Element-Plus:这是一套现成的"餐具",里面有各种做好的按钮、菜单、表单等组件,省去我们自己设计样式的麻烦。

4. Vue Router:这就是咱们的"服务员",负责根据客人(用户)点的菜(菜单选项)把对应的菜(页面)端上来。

安装完这些工具,咱们就可以开始"做菜"了!

三、项目搭建:从0开始建个"厨房"

1. 创建Vue3项目

打开命令行,找个你喜欢的文件夹,输入下面这个命令,然后按提示操作:

```bash

vue create vue3-menu-demo

```

这里要注意选Vue 3版本,然后把Router勾选上(这是重点!),其他配置默认就行。创建完成后进入项目文件夹:

```bash

cd vue3-menu-demo

```

2. 安装Element-Plus

这步就像咱们去超市买餐具,一行命令就能搞定:

```bash

npm install element-plus --save

```

然后在src/main.js里"打开餐具包装",把Element-Plus引入项目:

```javascript

import { createApp } from 'vue'

import App from './App.vue'

import router from './router'

// 引入Element-Plus

import ElementPlus from 'element-plus'

import 'element-plus/dist/index.css'

const app = createApp(App)

app.use(router)

// 使用Element-Plus

app.use(ElementPlus)

app.mount('app')

```

现在咱们的"厨房"就准备好了,接下来开始"准备菜谱"——配置路由。

四、路由配置:制定"菜单目录"

路由就像是餐厅的菜单目录,告诉系统有哪些菜(页面),每个菜在哪个位置。咱们打开src/router/index.js,这里就是配置路由的地方。

1. 基础路由结构

先看个简单的例子,就像菜单上得有"主食"、"炒菜"、"汤品"这些大类:

```javascript

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

// 导入页面组件(就像提前准备好各种菜品)

import Home from '../views/Home.vue'

import About from '../views/About.vue'

import Login from '../views/Login.vue'

import MainLayout from '../components/MainLayout.vue'

const routes = [

{

path: '/login', // 登录页面的"门牌号"

name: 'Login',

component: Login // 对应登录页面组件

},

{

path: '/', // 主页面的"门牌号"

name: 'MainLayout',

component: MainLayout, // 这是包含左侧菜单和右侧内容区的整体布局

children: [ // 子路由,就像"主食"下面的各种具体菜品

{

path: '', // 默认显示的页面(主食里的米饭)

name: 'Home',

component: Home,

meta: { title: '首页', icon: 'el-icon-s-home' } // 这里的meta存菜单需要的信息:标题和图标

},

{

path: 'about', // 相对路径,完整路径是 /about

name: 'About',

component: About,

meta: { title: '关于我们', icon: 'el-icon-info' }

}

]

}

]

const router = createRouter({

history: createWebHashHistory(),

routes

})

export default router

```

这里有几个关键点要记住:

- MainLayout:这是整个应用的"大餐桌",包含左侧菜单和右侧内容显示区

- children:子路由,这些页面会显示在MainLayout的右侧内容区

- meta:元数据,这里存了菜单需要显示的标题和图标,等下动态生成菜单就靠它

2. 路由元信息详解

就像菜品描述里会写"辣度:中辣"、"推荐指数:★★★★",路由的meta里也可以存各种信息:

- title:菜单上显示的文字,比如"首页"、"用户管理"

- icon:菜单前面的小图标,Element-Plus提供了很多现成的,比如`el-icon-s-home`是首页图标

- hidden:如果设为true,这个路由就不会显示在菜单上(就像隐藏菜单,需要暗号才能点)

- roles:可以用来控制权限,比如某些菜单只有管理员能看到

举个更复杂的例子,就像餐厅菜单会分很多类:

```javascript

// 这是一个更完整的路由配置示例

const routes = [

{

path: '/login',

name: 'Login',

component: Login,

meta: { hidden: true } // 登录页不在菜单显示

},

{

path: '/',

name: 'MainLayout',

component: MainLayout,

meta: { title: '主菜单', icon: 'el-icon-menu' },

children: [

{

path: '',

name: 'Home',

component: Home,

meta: { title: '首页', icon: 'el-icon-s-home' }

},

{

path: 'user',

name: 'User',

meta: { title: '用户管理', icon: 'el-icon-user' },

children: [ // 嵌套子菜单,就像"用户管理"下面有"用户列表"和"添加用户"

{

path: 'list',

name: 'UserList',

component: () => import('../views/user/List.vue'), // 懒加载组件,提高性能

meta: { title: '用户列表', icon: 'el-icon-s-order' }

},

{

path: 'add',

name: 'UserAdd',

component: () => import('../views/user/Add.vue'),

meta: { title: '添加用户', icon: 'el-icon-circle-plus' }

}

]

},

{

path: 'setting',

name: 'Setting',

component: () => import('../views/Setting.vue'),

meta: {

title: '系统设置',

icon: 'el-icon-setting',

hidden: true // 这个菜单不在左侧显示

}

}

]

}

]

```

五、页面结构:搭建"餐桌"和"展示区"

现在咱们有了菜单目录(路由配置),接下来要建"餐桌"——也就是页面布局。主要分为两部分:登录页和主布局页。

1. 登录页面(Login.vue)

这就像餐厅的大门,客人得先在这里"登记"才能进去。简单写个登录表单:

```vue

```

2. 主布局组件(MainLayout.vue)

这是咱们的"大餐桌",包含左侧菜单和右侧内容区:

```vue

```

这里的``就像是餐厅的展示窗口,点了哪个菜,这里就展示哪个菜。

3. 根组件(App.vue)

最后在App.vue里放个"总开关",根据路由显示不同的页面:

```vue

```

六、动态菜单组件:让"菜单"自动生成

最关键的部分来了——如何让菜单根据路由配置自动生成。就像餐厅每天会根据食材自动更新菜单,我们的菜单也要根据路由配置动态变化。

1. 创建MenuNav组件

新建src/components/MenuNav.vue,这个组件专门负责显示菜单:

```vue

```

2. 代码解析:让菜单"活"起来

这个组件的核心就在于"动态"两个字,咱们一点点来看:

- 获取路由数据:通过`router.options.routes`拿到我们在router/index.js里配置的所有路由。这就像餐厅经理把完整菜单给了服务员。

- 筛选菜单数据:找到名称是'MainLayout'的路由,它的children就是我们要显示的菜单列表。

- 递归生成菜单:用v-for遍历路由,如果路由有children(子菜单),就用``组件,否则用``组件。

- 图标显示:通过`:class="route.meta.icon"`动态绑定图标类名,这样路由配置里meta.icon是什么,这里就显示什么图标。

- 路由跳转:``组件加了router属性后,点击菜单会自动根据`:index`的值(也就是路由path)进行跳转。

七、菜单图标设置:给"菜品"加个好看的图标

菜单光秃秃的不好看,咱们给每个菜加个"小图标"。Element-Plus提供了很多现成的图标,就像餐厅会给菜品配个小图片。

1. 图标使用方法

在路由的meta里设置icon属性,值就是Element-Plus图标的类名:

```javascript

meta: { title: '首页', icon: 'el-icon-s-home' } // 首页图标

meta: { title: '用户管理', icon: 'el-icon-user' } // 用户图标

```

常用的图标类名可以参考Element-Plus官网的图标文档,这里列举几个常用的:

- el-icon-s-home:首页

- el-icon-user:用户

- el-icon-s-order:订单

- el-icon-setting:设置

- el-icon-shopping-cart:购物车

- el-icon-document:文档

- el-icon-message:消息

- el-icon-warning:警告

2. 自定义图标(高级技巧)

如果Element-Plus的图标不够用,咱们还可以用自己的图标,就像餐厅会自己设计特色菜品的图片。这里需要用到iconfont:

1. 去[iconfont官网](https://www.iconfont.cn/)选图标,添加到项目,下载代码

2. 把下载的iconfont.css文件放到src/assets目录

3. 在main.js里引入:`import './assets/iconfont.css'`

4. 在路由meta里使用:`meta: { icon: 'iconfont icon-myicon' }`(这里的iconfont是固定前缀,icon-myicon是你下载的图标类名)

八、常见问题解决:这些"坑"新手一定要注意

1. 菜单不显示?检查这3点!

- 路由配置问题:确保路由的meta里有title,没有设置hidden: true

- MainLayout路径:检查MenuNav组件里是不是正确找到了MainLayout的路由

- 组件引入:确认MenuNav组件正确导入到了MainLayout中

2. 点击菜单不跳转?可能是这2个原因

- 没加router属性:``组件必须加上router属性才会自动跳转

- index值不对:`:index`绑定的必须是路由的path,比如`/home`或`user/list`

3. 图标不显示怎么办?

- 类名错误:检查meta.icon的值是否正确,比如有没有少写`el-icon-`前缀

- 样式没引入:确认main.js里导入了Element-Plus的样式:`import 'element-plus/dist/index.css'`

- 缓存问题:有时候改了代码没生效,可以试试重启项目(npm run serve)

4. 子菜单展开/收起有问题?

- index重复:确保每个菜单的:index值是唯一的,不能重复

- children结构:子菜单必须放在children数组里,并且父菜单要用``

5. 登录后跳转到404页面?

这是因为路由配置的问题,检查:

- Login组件里登录成功后是不是跳转到了正确的路径(比如`router.push('/')`)

- MainLayout路由的path是不是'/',并且有默认子路由(path: '')

九、10个实用小技巧:让你的菜单更"聪明"

1. 菜单高亮保持

刷新页面后菜单高亮状态会消失?在``里加个`:default-active="$route.path"`,让它根据当前路由自动高亮:

```vue

```

2. 菜单折叠功能

想让菜单可以折叠?加个按钮控制折叠状态:

```vue

```

3. 面包屑导航

在MainLayout的main-content里加个面包屑,显示当前位置:

```vue

{{ item.meta.title }}

```

4. 权限控制

根据用户角色显示不同菜单,在MenuNav组件里过滤路由:

```javascript

// 假设当前用户角色是'admin'

const userRole = 'admin'

// 过滤只显示当前角色有权限的菜单

const filteredRoutes = routes.value.filter(route => {

// 如果路由没有roles配置,默认显示

if (!route.meta.roles) return true

// 如果有roles配置,检查当前用户角色是否在其中

return route.meta.roles.includes(userRole)

})

```

5. 菜单缓存

让右侧内容区切换时保持页面状态,在router-view外面包一层keep-alive:

```vue

```

6. 动态加载路由

登录后根据用户权限动态添加路由:

```javascript

// 在登录成功后

router.addRoute('MainLayout', { // 添加到MainLayout的children里

path: 'dashboard',

name: 'Dashboard',

component: () => import('../views/Dashboard.vue'),

meta: { title: '仪表盘', icon: 'el-icon-dashboard' }

})

```

7. 菜单图标颜色跟随高亮

让图标颜色和文字一起变化,在样式里添加:

```css

.el-menu-item.is-active i, .el-sub-menu__title.is-active i {

color: ffd04b !important; / 和active-text-color保持一致 /

}

```

8. 菜单点击防抖

防止快速点击菜单导致多次跳转,给菜单点击事件加防抖:

```javascript

import { debounce } from 'lodash'

const handleMenuClick = debounce((index) => {

router.push(index)

}, 300)

```

9. 菜单搜索功能

给菜单加个搜索框,快速找到想要的菜单:

```vue

v-model="searchText"

placeholder="搜索菜单"

size="small"

class="menu-search"

/>

```

10. 菜单滚动

菜单太多时出现滚动条:

```css

.sidebar {

overflow-y: auto; / 纵向滚动 /

}

/ 隐藏滚动条但保留功能 /

.sidebar::-webkit-scrollbar {

width: 4px;

}

.sidebar::-webkit-scrollbar-thumb {

background: 666;

border-radius: 2px;

}

```

十、新手避坑清单:这些错误千万别犯!

1. 路由path重复:每个路由的path必须唯一,否则会导致跳转混乱

2. 忘记加router-view:没有``,页面内容就没地方显示

3. meta.title没设置:菜单会显示undefined,一定要给每个路由加meta.title

4. 子路由用绝对路径:子路由的path前面不要加`/`,否则会从根路径开始

5. 菜单组件没导入:忘记在MainLayout里import MenuNav会导致菜单不显示

6. el-menu没有设置router:不加router属性,点击菜单不会跳转

7. index值不是字符串::index必须绑定字符串类型,数字可能会有问题

8. 路由name重复:虽然不影响功能,但会导致一些路由相关的功能异常

9. 样式作用域问题:给MenuNav加了scoped样式可能会导致Element-Plus样式不生效,需要用/deep/穿透

10. 忘记处理404页面:最好配置一个404路由,当访问不存在的路径时显示友好提示

十一、长期使用体验:这些优化让你用得更爽

用了一段时间这个导航菜单后,我总结了几个让体验更好的优化点:

1. 菜单状态持久化:把菜单折叠状态、上次选中的菜单等信息存在localStorage里,下次打开页面时恢复

2. 菜单懒加载:如果菜单很多,可以只加载当前展开的菜单,提高性能

3. 添加菜单动画:菜单展开收起时加个过渡动画,视觉效果更好

4. 响应式菜单:在手机上自动隐藏左侧菜单,通过按钮呼出,适应移动端

5. 错误监控:给菜单添加错误捕获,防止因为路由配置错误导致整个页面崩溃

举个菜单状态持久化的例子,在MenuNav组件里:

```javascript

// 页面加载时读取保存的状态

onMounted(() => {

const savedCollapse = localStorage.getItem('menuCollapse')

if (savedCollapse !== null) {

isCollapse.value = JSON.parse(savedCollapse)

}

// 获取路由数据...

})

// 监听折叠状态变化,保存到localStorage

watch(isCollapse, (newVal) => {

localStorage.setItem('menuCollapse', JSON.stringify(newVal))

})

```

这样用户关闭页面再打开,菜单的折叠状态会保持不变,体验更好。

话说回来,动态路由菜单其实就是把"死菜单"变成"活菜单",让网站结构更灵活、更容易维护。掌握了这个技能,你就可以轻松搭建各种后台管理系统、博客网站、电商平台的导航结构。关键在于理解路由和菜单的对应关系,以及如何用Vue的特性把它们动态关联起来。希望这篇教程能帮你真正搞懂Vue3+Element-Plus动态菜单的实现方法,快去动手试试吧!