涉及技术栈:Vue3、TS、Element Plus
目标:用Element Plus写一个菜单(通常是在写菜单的时候要创建一个数组来用v-for遍历)
1.批量渲染el-icon
我的习惯是先创建一个interface文件夹和index.ts
再搞个叫MenuList的interface:(注意import的时候不要漏了type关键字)
import type { Component } from "vue"
export interface MenuList{
path: string,//路由路径
name: string,
label: string,//显示的文字
icon?: Component,//icon组件
children?: MenuList[]//子菜单
}
之前找过用string类表示icon的示例,没一个成的(#`Д´)ノ
总结还是直接用Component类容易实现一些
组件内的代码: 利用刚刚的MenuList创建一个存放菜单信息的数组
script部分
import type { MenuList } from '@/interface'
import { ref } from 'vue'
import { House, Notebook } from '@element-plus/icons-vue'
//ref用作响应式数据,不用ref直接用数组也没问题
const menulist = ref<MenuList[]>([
{
path: '/home',
name: 'home',
label: '首页',
icon: House,
},
{
path: '/epochhistory',
name: 'epochhistory',
label: '训练记录',
icon: Notebook,
},
//其他菜单选项...
])
template部分
<el-menu mode="horizontal" :router="true">
<el-menu-item v-for="item in menulist" :index="item.path" :key="item.path">
<!-- ↓渲染icon的核心 -->
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<!-- ↑渲染icon的核心 -->
<span>{{ item.label }}</span>
</el-menu-item>
</el-menu>
解释:
你在el-icon官网的最底部可以看到一堆的图标,如果选择房子图标,点一下可以复制获得<el-icon><House /></el-icon>
看回代码:
<component :is="item.icon"></component>
的部分正是替换了el-icon标签中间的<House />
效果图:
2.带子菜单的组件怎么渲染
如果你想写带子菜单的数组,建议先把menulist分成noChildern和hasChildren(无子菜单与有子菜单)两个新的数组,分开遍历
这里的menulist我就不加icon了,大家可以自己尝试一下改一下
script:
//有子菜单与无子菜单两种都有的menulist
const menulist = ref([
{
path: '/home',
name: 'home',
label: '首页',
},
{
path: '/mall',
name: 'mall',
label: '商品管理',
},
{
path: '/user',
name: 'user',
label: '用户管理',
},
{
path: '/other',
label: '其他',
children: [
{
path: '/page1',
name: 'page1',
label: '页面1',
},
{
path: '/page2',
name: 'page2',
label: '页面2',
}
]
}
])
//核心:把原数组分成两个数组
const noChildren = computed(() => list.value.filter(item => !item.children))
const hasChildren = computed(() => list.value.filter(item => item.children))
template:
<el-menu>
<!-- 无子菜单 -->
<el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path">
<span>{{ item.label }}</span>
</el-menu-item>
<!-- 有子菜单 -->
<el-sub-menu v-for="item in hasChildren" :index="item.path" :key="item.path">
<template #title>
<!-- <el-icon><component :is="item.icon"><component /><el-icon /> -->
<span>{{ item.label }}</span>
</template>
<el-menu-item-group>
<el-menu-item
v-for="subItem in item.children"
:index="subItem.path"
:key="subItem.path"
>
<!-- <el-icon><component :is="subItem.icon"><component /><el-icon /> -->
<span>{{ subItem.label }}</span>
</el-menu-item>
</el-menu-item-group>
</el-sub-menu>
</el-menu>
注意: 这里举的例子适用于只有一层子菜单,
如果你的要求是子菜单内还有有更小的子菜单(这里叫他子子菜单好了)
我的建议有两个:
- 你的菜单比较臃肿的话,应该考虑修改你的菜单结构
- 如果不能改的话,不要用v-for遍历,直接写会更快更简单些,具体操作可以看这个页面的第一个例子(关于顶栏的部分)
有什么其他问题欢迎在评论区提出哦,希望这篇文章对你有所帮助(吐舌)
じゃね!