动态渲染element-ui导航菜单

发布时间:2024-03-07 11:51:56 浏览量:215次

需求背景

在vue中正常写死的使用 el-menu 组件是没有问题的。但是如果数据是动态的时候,并且菜单数据的层级嵌套的也不知道。这个时候在使用该组件时就会遇到一个问题。

<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
  <el-menu-item index="1">处理中心</el-menu-item>
  <el-submenu index="2">
    <template slot="title">我的工作台</template>
    <el-menu-item index="2-1">选项1</el-menu-item>
    <el-menu-item index="2-2">选项2</el-menu-item>
    <el-menu-item index="2-3">选项3</el-menu-item>
    <el-submenu index="2-4">
      <template slot="title">选项4</template>
      <el-menu-item index="2-4-1">选项1</el-menu-item>
      <el-menu-item index="2-4-2">选项2</el-menu-item>
      <el-menu-item index="2-4-3">选项3</el-menu-item>
    </el-submenu>
  </el-submenu>
  <el-menu-item index="3" disabled>消息中心</el-menu-item>
  <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
</el-menu>

如上面这一段代码,在与el-menu-item组件同级的还有el-submenu组件,而el-submenu组件则渲染的是当前节点的子级数据。然而在你根本不知道数据哪一个节点会出现子级数据时,在template中就无法使用类似v-for这样的循环来渲染数据。

此时就想了,能不能在el-menu-item外面嵌套一层标签,如果我们发现数据又子级数据,就让这个数据使用el-submenu组件。乍听上去好像可行,然而是不行的,最起码数据嵌套多少层你不知道,也就不知道需要预设写多少层。

此时又来灵感了,把el-submenu封装一层,在封装的组件里面再使用这个封装的组件,这样就会形成一个递归的效果,也就解决了层级嵌套的问题。

设想很美好,然而事实并不然,这套组件之间根本容不下其他任何组件或标签

解决方案

其实想要的效果就是根据数据,在该渲染el-menu-item的地方渲染el-menu-item,在该渲染el-submenu的地方渲染el-submenu。如果这标签是一堆字符串的话,我们使用一个函数的编写方式不就可以解决所有的问题?有的,其实是vue里面的老api了。使用render函数来解决这个问题。

  • 首先我们创建一个menu文件,在该文件中使用render函数。
  • 封装menu
export default {
	props: {
  	menuData: {
    	type: Array,
      default: () => ([])
    }
  },
  render() {
  	const menuItem = (item, index) => {
      const renderName = (item.children && item.children.length) ? 'submenu' : 'menuItem'
      const jx = {
        submenu: (function() {
          return (
            <el-submenu index={String(index)}>
              <template slot='title'>
                <img class='menu-m-icon' src={item.iconPath} style={imgStyle} />
                {item.name}
              </template>
              {
                listFn(item.children).map((t, i) => menuItem(t, `${index}-${i}`))
              }
            </el-submenu>
          )
        })(),
        menuItem: (
          <el-menu-item index={String(index)}>
            { item.name }
          </el-menu-item>
        )
      }
      return jx[renderName]
    }
    return (
      <el-menu>
        {this.menuData.map((t, index) => menuItem(t, index))}
      </el-menu>
    )
  }
}
  • 使用menu组件
<template>
  	<menu : menuData="menuData"></menu>
  </template>
<script>
      import menu from './menu'
      export default {
				components: { menu },
        data() {
        	return {
          	menuData: [
              { name: '项目一', id: 1 },
              { name: '项目二', id: 2, children: [
               { name: '项目2-1' },
               { name: '项目2-2',  children: [
                 { name: '项目2-2-1' }			
               ]}
               ] },
              { name: '项目三', id: 3 },
            ]
          }
        }
			}
</script>

热门课程推荐

热门资讯

请绑定手机号

x

同学您好!

您已成功报名0元试学活动,老师会在第一时间与您取得联系,请保持电话畅通!
确定