Vue 展示一个带有复选框的树形菜单,并通过按钮收集已选中的节点
<template>
<div>
<el-tree
ref="tree"
:data="menuOptions"
:props="treeProps"
node-key="id"
:default-checked-keys="menuId"
show-checkbox
@check="handleCheck"
>
</el-tree>
<button @click="logCheckedNodes">收集已选节点</button>
<pre>{{ JSON.stringify(checkedNodes, null, 2) }}</pre>
</div>
</template>
<script>
export default {
data() {
return {
// menuId: [543, 575, 576, 688, 689, 690, 577, 691, 692],
menuId: [ 688, 689, 690, 691, 692 ],
menuOptions: [
{ id: 543, label: "首页", business_type: 0 },
{
id: 575,
label: "up评级后台",
business_type: 0,
children: [
{
id: 576,
label: "up评级",
business_type: 0,
children: [
{ id: 688, label: "导入评级", business_type: 0 },
{ id: 689, label: "评级打分", business_type: 0 },
{ id: 690, label: "分页获取评级", business_type: 0 }
]
},
{
id: 577,
label: "运营复评",
business_type: 0,
children: [
{ id: 691, label: "重新评级", business_type: 0 },
{ id: 692, label: "分页获取评级", business_type: 0 }
]
},
{
id: 578,
label: "评级查询",
business_type: 0,
children: [
{ id: 693, label: "导出评级明细", business_type: 0 },
{ id: 694, label: "分页获取评级", business_type: 0 },
{ id: 695, label: "导入扶持up", business_type: 0 },
{ id: 696, label: "导入非扶持up", business_type: 0 },
{ id: 697, label: "主播重新评级", business_type: 0 }
]
}
]
}
],
treeProps: {
label: 'label',
children: 'children',
disabled: (data) => this.menuId.includes(data.id)
},
checkedNodes: []
};
},
methods: {
getCheckedNodes(nodes, checkedKeys) {
return nodes.reduce((acc, node) => {
if (checkedKeys.includes(node.id) && !this.menuId.includes(node.id)) {
const newNode = { ...node };
if (node.children) {
newNode.children = this.getCheckedNodes(node.children, checkedKeys);
}
acc.push(newNode);
} else if (node.children) {
const childNodes = this.getCheckedNodes(node.children, checkedKeys);
if (childNodes.length > 0) {
const partialNode = { ...node, children: childNodes };
acc.push(partialNode);
}
}
return acc;
}, []);
},
logCheckedNodes() {
const checkedKeys = this.$refs.tree.getCheckedKeys(true);
const checkedNodes = this.getCheckedNodes(this.menuOptions, checkedKeys);
this.checkedNodes = checkedNodes;
console.log('Checked Nodes:', checkedNodes);
}
}
};
</script>
<style scoped>
/* 样式可以保留 */
</style>
这个代码使用 Vue.js 和 Element UI 的 <el-tree>
组件来展示一个带有复选框的树形菜单,并通过按钮收集已选中的节点。以下是代码的详细解释:
模板部分 (<template>
)
<template>
<div>
<el-tree
ref="tree"
:data="menuOptions"
:props="treeProps"
node-key="id"
:default-checked-keys="menuId"
show-checkbox
@check="handleCheck"
>
</el-tree>
<button @click="logCheckedNodes">收集已选节点</button>
<pre>{{ JSON.stringify(checkedNodes, null, 2) }}</pre>
</div>
</template>
-
<el-tree>
组件: 用于展示树形数据。ref="tree"
: 用于引用该组件实例。:data="menuOptions"
: 树的数据来源。:props="treeProps"
: 控制树结构的属性配置。node-key="id"
: 唯一节点标识字段。:default-checked-keys="menuId"
: 默认选中的节点。show-checkbox
: 显示复选框。@check="handleCheck"
: 选中节点时触发的事件。
-
按钮: 用于触发
logCheckedNodes
方法,收集并展示已选中的节点。 -
格式化的 JSON 预览: 用于展示
checkedNodes
。
脚本部分 (<script>
)
<script>
export default {
data() {
return {
menuId: [688, 689, 690, 691, 692],
menuOptions: [
{ id: 543, label: "首页", business_type: 0 },
{
id: 575,
label: "up评级后台",
business_type: 0,
children: [
{
id: 576,
label: "up评级",
business_type: 0,
children: [
{ id: 688, label: "导入评级", business_type: 0 },
{ id: 689, label: "评级打分", business_type: 0 },
{ id: 690, label: "分页获取评级", business_type: 0 }
]
},
{
id: 577,
label: "运营复评",
business_type: 0,
children: [
{ id: 691, label: "重新评级", business_type: 0 },
{ id: 692, label: "分页获取评级", business_type: 0 }
]
},
{
id: 578,
label: "评级查询",
business_type: 0,
children: [
{ id: 693, label: "导出评级明细", business_type: 0 },
{ id: 694, label: "分页获取评级", business_type: 0 },
{ id: 695, label: "导入扶持up", business_type: 0 },
{ id: 696, label: "导入非扶持up", business_type: 0 },
{ id: 697, label: "主播重新评级", business_type: 0 }
]
}
]
}
],
treeProps: {
label: 'label',
children: 'children',
disabled: (data) => this.menuId.includes(data.id)
},
checkedNodes: []
};
},
methods: {
getCheckedNodes(nodes, checkedKeys) {
return nodes.reduce((acc, node) => {
if (checkedKeys.includes(node.id) && !this.menuId.includes(node.id)) {
const newNode = { ...node };
if (node.children) {
newNode.children = this.getCheckedNodes(node.children, checkedKeys);
}
acc.push(newNode);
} else if (node.children) {
const childNodes = this.getCheckedNodes(node.children, checkedKeys);
if (childNodes.length > 0) {
const partialNode = { ...node, children: childNodes };
acc.push(partialNode);
}
}
return acc;
}, []);
},
logCheckedNodes() {
const checkedKeys = this.$refs.tree.getCheckedKeys(true);
const checkedNodes = this.getCheckedNodes(this.menuOptions, checkedKeys);
this.checkedNodes = checkedNodes;
console.log('Checked Nodes:', checkedNodes);
}
}
};
</script>
-
数据:
menuId
: 默认选中的节点 ID 数组。menuOptions
: 树形数据。treeProps
: 配置树结构显示的属性。checkedNodes
: 保存已选中的节点数据。
-
方法:
getCheckedNodes
: 递归获取已选中的节点,排除掉menuId
中的节点。logCheckedNodes
: 通过树的实例this.$refs.tree
获取选中的节点 ID,并调用getCheckedNodes
获取对应的节点数据,保存到checkedNodes
。
详解getCheckedNodes
是一个递归函数,用于收集所有被选中的节点并返回一个不包含在 menuId
数组中的节点列表。以下是函数的详细解释:
getCheckedNodes(nodes, checkedKeys) {
return nodes.reduce((acc, node) => {
// 判断当前节点是否在选中列表中并且不在默认选中的节点列表中
if (checkedKeys.includes(node.id) && !this.menuId.includes(node.id)) {
const newNode = { ...node };
// 如果当前节点有子节点,递归调用 getCheckedNodes 收集子节点
if (node.children) {
newNode.children = this.getCheckedNodes(node.children, checkedKeys);
}
// 将处理好的节点添加到结果集中
acc.push(newNode);
} else if (node.children) {
// 如果当前节点不在选中列表中,但有子节点,将子节点传递下去处理
const childNodes = this.getCheckedNodes(node.children, checkedKeys);
if (childNodes.length > 0) {
// 如果子节点中有任何节点被选中,将部分更新的节点添加到结果集中
const partialNode = { ...node, children: childNodes };
acc.push(partialNode);
}
}
return acc;
}, []);
}
详细解释
-
入参:
nodes
: 当前处理的节点列表。checkedKeys
: 所有被选中的节点 ID 数组。
-
返回值:
- 返回一个包含被选中的节点及其层级结构的数组。
-
步骤:
-
1. 初始化累加器: 使用数组
reduce
方法,初始化一个空数组acc
作为累加器。 -
2. 遍历节点:
-
对
nodes
的每一个node
进行处理: -
3.a. 是否选中并不在默认选中节点中:
-
如果当前节点
node.id
在checkedKeys
中,并且不在menuId
中,说明该节点应该被选中。 -
新建一个
newNode
,复制当前节点的所有属性(浅拷贝)。 -
3.a.i. 递归处理子节点:
- 如果当前节点有子节点
children
,递归调用getCheckedNodes
处理子节点。 - 将处理后的子节点数组赋值给
newNode.children
。
- 如果当前节点有子节点
-
3.a.ii. 添加到累加器:
- 将
newNode
添加到累加器acc
中。
- 将
-
-
3.b. 子节点处理:
-
如果当前节点没有被选中,但有子节点
children
,继续处理子节点: -
3.b.i. 递归处理子节点:
- 以当前节点的子节点作为参数调用
getCheckedNodes
。 - 返回的子节点数组
childNodes
。
- 以当前节点的子节点作为参数调用
-
3.b.ii. 添加部分节点:
- 如果
childNodes
中有节点,说明某些子节点被选中,创建一个partialNode
。 - 将
partialNode
(包含未选中的当前节点和被选中的子节点)添加到acc
中。
- 如果
-
-
-
4. 返回累加器: 完成所有节点遍历,返回累加器
acc
,它包含所有被选中的节点及其层级结构。
-
这个函数确保无论节点在树的哪个层级,只要被选中且不在默认选中的节点列表中,都将被捕获并保存在结果中。
原文地址:https://blog.csdn.net/weixin_41987016/article/details/142452668
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!