基于Vue+elementUI menu组件的动态渲染多级目录
需求描述
后端接口是,通过父级目录id查询子级目录列表,所以我需要动态渲染一个多级目录,目录深度不确定
后端返回数据参考
比较关键的数据是
id
目录id
name
目录名字
level
目录所在层级
exitSon
是否有子层级
解决方法
我使用了elementUi的menu组件,因为项目是基于Vue2 的所有 是用的"element-ui": "2.15.10"
menu组件地址:https://element.eleme.cn/#/zh-CN/component/menu
具体代码
MultiLevelMenu
组件
<template>
<el-submenu v-if="isSubmenu" :index="computedIndex">
<template slot="title">{{ item.fieldName }}</template>
<MultiLevelMenu
v-for="(subItem, subIndex) in item.submenu"
:key="subIndex"
:item="subItem"
:index="computeChildIndex(subIndex)"
:level="level + 1"
/>
</el-submenu>
<el-menu-item v-else :index="computedIndex">
{{ item.fieldName }}
</el-menu-item>
</template>
<script>
export default {
name: "MultiLevelMenu",
props: {
item: Object,
index: String,
level: Number,
},
computed: {
//判断是否有子级目录
isSubmenu() {
return Array.isArray(this.item.submenu);
},
//计算目录的index
computedIndex() {
if (this.level === 0) {
return (this.index).toString();
} else if (this.$parent && typeof this.$parent.computedIndex === 'string') {
return `${this.$parent.computedIndex}-${this.index}`;
} else {
return (this.index).toString();
}
},
},
methods: {
//计算目录的index
computeChildIndex(subIndex) {
if (this.level === 0) {
return subIndex.toString();
} else if (typeof this.computedIndex === 'string') {
return `${this.computedIndex}-${subIndex}`;
} else {
return subIndex.toString();
}
},
},
};
</script>
关于computeChildIndex
函数和computedIndex
函数,我把目录的路径存储在menu的index属性里面
比如index是1-3-3
就代表是menu[1].children[3]..children[3]
第一层第一个–>第二层的第三个–>第三层的第三个
其实可以不使用这样的方式存储menu的路径,elementUI官方提供相应的方法
indexPath
是一个数组,如上1-3-3
,它会自动存储 [1,3,3]
当时作者使用1-3-3
方式是因为menu组件抽风了,就是没有存储到路径。。。。
然后怎么在父组件中使用MultiLevelMenu
呢
<el-menu :default-active="activeMenuIndex"
mode="vertical"
@open="handleMenuOpen"
@select="handleItemSel"
unique-opened
>
<MultiLevelMenu
v-for="(item, index) in menu"
:key="index"
:item="item"
:index="String(index)"
:level="item.level"
/>
</el-menu>
el-menu
相关属性可以查询官网解释,此处简单解释一下
:default-active="activeMenuIndex"
当前激活菜单的index
String
类型
mode=“vertical” 模式 vertical表示垂直显示
@open=“handleMenuOpen” 目录展开事件
@select=“handleItemSel” 子叶目录选中事件
unique-opened 是否只保持一个子菜单的展开
<MultiLevelMenu
v-for="(item, index) in menu"//循环相关 menu表示你的目录列表 Array类型
:key="index"//循环相关
:item="item"//当前项
:index="String(index)"//index
:level="item.level"//层级
/>
其他相关实现
父组件script部分,仅供参考。
<script>
export default {
data(){
return{
//当前激活菜单的index
activeMenuIndex: '1',
//目录
menu:[],
}
},
created() {
//第一次加载目录
this.getMenuTopList();
},
methods: {
//目录展开事件
handleMenuOpen(index, indexPath) {
console.log(index, indexPath);
//1.使用index(1-3-3方式)
let currentMenu=this.getCurrentMenu(index);
//发送请求
//请求成功之后更新数据
const submenu=res.data//可能需要对请求成功的数据做一些转换
this.$set(currentMenu,'submenu',submenu)
//2.使用indexPath([1,3,3]方式)
let currentMenu=null;
for (let i=0;i<indexPath.length;i++){
if (i===0){
currentMenu=this.menu[arr[i]]
}else {
if (currentMenu&¤tMenu.submenu&¤tMenu.submenu.length>0){
currentMenu=currentMenu.submenu[arr[i]]
}
}
}
//发送请求
//请求成功之后更新数据
const submenu=res.data//可能需要对请求成功的数据做一些转换
this.$set(currentMenu,'submenu',submenu)
}
},
//子叶目录点击事件
handleItemSel(index, indexPath) {
console.log(index, indexPath);
},
//第一次加载目录
getMenuTopList(){
//向后端发送请求
this.menu=res.data//可能需要对请求成功的数据做一些转换
},
// 根据index路径获取当前的目录对象
getCurrentMenu(index){
const arr = index.split('-').map(Number);
let currentMenu=null;
for (let i=0;i<arr.length;i++){
if (i===0){
currentMenu=this.menu[arr[i]]
}else {
if (currentMenu&¤tMenu.submenu&¤tMenu.submenu.length>0){
currentMenu=currentMenu.submenu[arr[i]]
}
}
}
return currentMenu;
},
}
}
</script>
实战代码参考
下图是作者的实际项目的代码,仅供参考
data部分
本文由博客一文多发平台 OpenWrite 发布!