DFS 创建分级菜单
菜单级别不确定,想要自适应,且可以折叠的菜单。
数据是一个数组。
<template>
<div class="Level" ref="Level">
</div>
</template>
import {ref} from 'vue'
export default{
data(){
Level:ref(null),
menuData: [
{
parentid: 0,
name: "医院",
contents: [
{
parentid: 1,
name: "外科",
contents: [],
level: 2,
para: {
"para1": "值1",
"para2": "值2"
}
}
],
]
}
}
为什么想用DFS呢?
因为数组内对象嵌套的数组,又不知道后端确切最高返回几层,只能按照深度读取,并且为每个节点逐深度的创建DOM,为每个节点(不包括只有父节点)添加点击展开和隐藏事件,使用dispaly属性完成。
每个级别的缩进?
它依靠contentsl对象中的leve属性判断当前div的级别,设置margin-left 为指定leve比例可以实现。
阻止事件冒泡?
内部的div
元素被外部的div
元素的点击事件冒泡到了顶层。当一个元素触发了某个事件,这个事件会冒泡到其父元素,直到根元素。如果不阻止点击任意的级别都会触发最顶层的div,将所有元素都折叠。使用事件对象event.stopPropagation();阻止事件冒泡。
DFS实现分级菜单
DFSLevel(node, parentElement) {
if (!node) return;
// 为当前节点创建一个div元素
var text = document.createElement("div");
text.innerHTML = node.name;
text.style.marginLeft=(10*node.level)+"px";
// 存在子集
if (node.contents && Array.isArray(node.contents) && node.contents.length > 0) {
// 添加点击事件,实现隐藏和显示子元素的功能
text.addEventListener('click', (event) => {
event.stopPropagation(); // 阻止事件冒泡
// 获取子元素的div
var childrenDivs = text.querySelectorAll('div');
// 显隐切换
childrenDivs.forEach(div => {
if(div.style.display=='block') div.style.display ='none';
else div.style.display = 'block'
});
});
node.contents.forEach(subNode => {
this.DFSLevel(subNode, text); // 递归
});
}
parentElement.appendChild( text);
},
initMenu() {
// 从根节点开始递归
this.menuData.forEach(rootNode => {
this.DFSLevel(rootNode, this.$refs.Level);
});
}
虽然Vue 可以通过v-for 和v-if 层层判断,但是我真的受够了