vue3+elementplus根据数据渲染菜单并实现路由跳转

1,237 阅读2分钟

u=1525641228,2203598208&fm=253&fmt=auto&app=138&f=JPEG.webp

假如有这么一组数据,需要根据数据动态地渲染出菜单,并且实现路由跳转,那么该怎么做呢?

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>

这样,一个完整的菜单就渲染出来了,效果图如下:

snipaste_20230908_021816.png

为每个菜单绑定跳转路由

渲染出来后还要为菜单绑定路由,这样菜单的功能才是完整的。

为菜单添加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属性。

这样一个根据数据渲染,并可跳转路由的菜单就完成了。