vue3+ElementPlus实现无限级菜单ElMenu

735 阅读1分钟

直接上代码,因为是.vue文件,所以这里使用h函数实现,也可以使用tsx,看上去会更简洁一些。

<script lang="ts">
import { ElMenu, ElMenuItem, ElSubMenu, ElIcon } from 'element-plus';
import { h, defineComponent } from 'vue';
import type { VNode } from 'vue';
import * as Icon from "@element-plus/icons-vue";
import { useRoute } from 'vue-router';

export default defineComponent({
  props: {
    isCollapse: { type: Boolean, required: true },// 是否收缩
    activeIndex: { type: String, default: "1" },// 默认选中
    menuList: { type: Array, default: [] },// 菜单列表
  },
  setup(props) {
    const $route = useRoute();

    // 渲染图标
    function renderIcon(icon: string): VNode {
      return h(ElIcon, null, {
        default: () => h(Icon[icon], { style: { fontSize: '16px' } })
      })
    }

    // 渲染子菜单
    function renderMenu(list: any[]): VNode[] {
      const res: VNode[] = list.map(item => {
        let ele: VNode;
        if (!item.children || item.children.length === 0) {
          ele = h(ElMenuItem, { index: item.path }, { default: () => item.icon && renderIcon(item.icon), title: () => h('span', null, item.name) })
        } else {
          ele = h(ElSubMenu, { index: item.path }, { title: () => [item.icon && renderIcon(item.icon), h('span', null, item.name)], default: () => renderMenu(item.children) })
        }
        return ele;
      })
      return res;
    }

    return () => h(ElMenu, {
      defaultActive: $route.path,
      class: 'el-menu-vertical-demo',
      uniqueOpened: true,
      collapse: props.isCollapse,
      router: true
    }, { default: () => renderMenu(props.menuList) })

  }
})
</script>

<style lang="scss" scoped>
.el-menu {
  border-bottom: none;
  height: 100%;

  .el-menu-item {
    &.is-active {
      background-color: #f9f9f9;
    }
  }
}

.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
}
</style>