背景:根据后端返回数据生成多级菜单,菜单项可能会有很深的层级,如果直接使用elementUI 去编写会写很深的层级,代码繁杂,一旦后面菜单项有改动又不利于维护
如何做到多级菜单?使用递归组件
- <el-menu
- default-active="2"
- class="el-menu-vertical-demo"
- @open="handleOpen"
- @close="handleClose"
- background-color="#545c64"
- text-color="#fff"
- active-text-color="#ffd04b">
- <el-submenu index="1">
- <template slot="title">
- <i class="el-icon-location">i>
- <span>导航一span>
- template>
- <el-submenu index="1-4">
- <template slot="title">选项4template>
- <el-menu-item index="1-4-1">选项1el-menu-item>
- el-submenu>
- el-submenu>
- <el-menu-item index="4">
- <i class="el-icon-setting">i>
- <span slot="title">导航四span>
- el-menu-item>
- el-menu>
主要思路:
- <template v-if="hasOneChild(item.children, item) && (!oneChild.children || oneChild.noShowChild)">
- <app-link v-if="item.redirect != 'noRedirect' && item.meta" :to="resolvePath(item.path)">
- <el-menu-item :index="resolvePath(item.path)" class="submenu-title-noDropdown">
- <Item v-if="item.meta" :icon="item.meta.icon" :title="item.meta.title">Item>
- el-menu-item>
- app-link>
- template>
-
-
- <el-submenu v-else :index="resolvePath(item.path)">
- <template slot="title" v-if="item.meta">
-
- <Item :icon="item.meta.icon" :title="item.meta.title">Item>
- template>
-
- <sidebar-item
- v-for="child in item.children"
- :key="child.path"
- :item="child"
- :base-path="resolvePath(child.path)"
- class="nest-menu"
- >sidebar-item>
- el-submenu>
- // 判断当前菜单是否有子菜单
- hasOneChild(children = [], item) {
- // 判断如果菜单是隐藏直接不显示
- // if(item.hidden) return false;
- if (children.length === 0) return false;
- const showChildArr = children.filter(child => {
- console.log(child);
-
- if (child.hidden) return false;
- else return true;
- });
-
- // 没有找到child说明没有子菜单
- if (showChildArr.length === 0) {
- this.oneChild = { ...item, path: item.path, noShowChild: true };
- return true;
- }
- console.log(this.oneChild, "this.oneChild");
-
- return false;
- },
- export default {
- name: "Item",
- functional: true,
- // 组件传入的数据
- props: {
- title: {
- type: String,
- default: ""
- },
- icon: {
- type: String,
- default: ""
- }
- },
- // render函数生成虚拟节点
- render(h, context) {
- //
- // {{item.meta.title}}
- const { title, icon } = context.props; //获取传入的属性
- const vNode = [];
- if (icon) {
- const iconClass = `iconfont ` + icon;
- vNode.push(<i class={iconClass} style="font-size:18px;">i>);
- }
- if (title) {
- // JSX语法
- vNode.push(<span style="margin-left:8px;">{title}span>);
- }
- return vNode;
- }
- };