假如有这么一组数据,需要根据数据动态地渲染出菜单,并且实现路由跳转,那么该怎么做呢?
interface MenuItem {
id: number;
name: string;
index: string;
icon?: Component;
children?: MenuItem[];
}
const menulist: MenuItem[] = [
{
id: 1,
name: "首页",
index: "/home/admin-home",
icon: House,
},
{
id: 2,
name: "用户管理",
index: "/home/users",
icon: User,
},
{
id: 101,
name: "商品管理",
index: "/prouduct-management",
icon: Goods,
children: [
{
id: 102,
name: "产品列表",
index: "/home/goods",
},
{
id: 103,
name: "品牌列表",
index: "/home/brand",
},
{
id: 104,
name: "类型列表",
index: "/home/type",
},
{
id: 105,
name: "颜色列表",
index: "/home/color",
},
{
id: 106,
name: "尺寸列表",
index: "/home/size",
},
],
},
];
渲染菜单
首先需要准备一个能够进行动态渲染的容器:<component>,该标签是vue的内置标签,专门用于动态渲染组件或者元素。
该标签携带一个is属性,is可以是字符串也可以是注册的组件名,实际渲染的组件由is属性决定,下面是官网示例:
<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
</script>
<template>
<component :is="Math.random() > 0.5 ? Foo : Bar" />
</template>
就用这个标签来渲染菜单组件:
渲染一级菜单
import { ElSubMenu, ElMenuItem } from 'element-plus';
<el-menu
active-text-color="#fff"
background-color="#2b2c44"
class="el-menu-vertical-demo"
text-color="#aaa"
>
<!-- 根据数据渲染` <el-sub-menu/>`或`<el-menu-item>`标签 -->
<component
v-for="item in menulist"
:key="item.id"
:is="item.children?ElSubMenu:ElMenuItem"
>
</component>
</el-menu>
为菜单添加对应图标和标题
<component
v-for="item in menulist"
:key="item.id"
:is="item.children?ElSubMenu:ElMenuItem"
>
<!-- <el-sub-menu/> 标签需要使用具名插槽 #title添加 -->
<template v-if="item.children" #title>
<el-icon v-if="item.icon">
<!-- 图标属性类型是Component 所以使用<component/> 标签渲染 -->
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.name }}</span>
<!-- <el-menu-iten/>标签 -->
<span v-if="!item.children">
<el-icon v-if="item.icon">
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.name }}</span>
</span>
</template>
</component>
这样一级菜单就渲染好了,接下来渲染二级菜单
<el-menu
active-text-color="#fff"
background-color="#2b2c44"
class="el-menu-vertical-demo"
text-color="#aaa"
>
<component
:is="item.children?ElSubMenu:ElMenuItem"
v-for="item in menulist"
:key="item.id"
:index="item.index"
>
<!-- -->
<template v-if="item.children" #title>
<el-icon v-if="item.icon">
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.name }}</span>
</template>
<span v-if="!item.children">
<el-icon v-if="item.icon">
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.name }}</span>
</span>
<!-- 二级菜单和一级菜单渲染逻辑一样 -->
<el-menu-item
v-for="subItem in item.children"
:key="subItem.id"
:index="subItem.index"
>
{{ subItem.name }}
</el-menu-item>
</component>
</el-menu>
这样,一个完整的菜单就渲染出来了,效果图如下:
为每个菜单绑定跳转路由
渲染出来后还要为菜单绑定路由,这样菜单的功能才是完整的。
为菜单添加router属性,表示启用vue-router 模式,添加default-active属性表示页面加载时默认激活菜单的 index。
<el-menu
active-text-color="#fff"
background-color="#2b2c44"
class="el-menu-vertical-demo"
:default-active="defaultActive"
text-color="#aaa"
router
>
</el-menu>
// 创建一个响应式变量 获取当前路由路径 将变量绑定到`default-active`属性上,这样跳转到对应路由相
// 应的菜单也会高亮
const defaultActive = ref<string>(router.currentRoute.value.path)
启用router模式后,就会在激活导航时以index作为path进行路由跳转,上面在渲染菜单的时候已经添加了index属性。
这样一个根据数据渲染,并可跳转路由的菜单就完成了。