el-tree选中数据重组成树

vue+element-ui 实现el-tree选择重新生成一个已选中的值组成新的数据树,效果如下

html 复制代码
<template>
	<div  class="flex">
		<el-tree class="tree-row" :data="list" ref="tree" :props="{children: 'children', label: 'itemCategoryName'}" show-checkbox node-key="id" default-expand-all  @check-change="getChecked">
		</el-tree>
		<el-tree class="tree-row" :data="selectedTreeData"  :props="{children: 'children', label: 'itemCategoryName'}"  node-key="id" default-expand-all   :expand-on-click-node="false">
			<span class="custom-tree-node" slot-scope="{ node, data }">
				<span>{{ node.label }}</span>
				<span>
				<el-button
					type="text"
					size="mini"
					@click="() => remove(node, data)">
					Delete
				</el-button>
				</span>
			</span>
		</el-tree>
	</div>
</template>
<script>
export default {
	data() {
		return {
			list: [
				{
					"id": "4100000000000071",
					"itemCategoryCode": "001",
					"itemCategoryName": "白酒类",
					children: [{
						"id": "41000020000000071",
						"itemCategoryCode": "0012",
						"itemCategoryName": "白酒类2",
						children: [{
							"id": "41000040000000071",
							"itemCategoryCode": "0014",
							"itemCategoryName": "白酒类4",
						},
						{
							"id": "41000050000000071",
							"itemCategoryCode": "0015",
							"itemCategoryName": "白酒类5",
						},
						{
							"id": "41000060000000071",
							"itemCategoryCode": "0016",
							"itemCategoryName": "白酒类6",
						}]
					},
					{
						"id": "41000030000000071",
						"itemCategoryCode": "0013",
						"itemCategoryName": "白酒类3",
					}]
				},
			],
			// selectedIds: ['41000040000000071', "41000060000000071"],
			selectedTreeData:[]
		}
	},
	created() {
	},
	methods: {
		getChecked() {
			this.selectedIds = this.$refs.tree.getCheckedKeys(true);
            this.extractSubtrees();
		},
		extractSubtrees() {
			const subtrees = [];
			for (const id of this.selectedIds) {
				const subtree = this.extractSubtree(this.list, id);
				if (subtree) {
					subtrees.push(subtree);
				}
			}
			this.selectedTreeData = this.mergeSubtrees(subtrees);
		},
		extractSubtree(treeData, targetId) {
			for (const node of treeData) {
				if (node.id === targetId) {
					// return this.cloneAndFilterChildren(node); 可以用这个也可以用下边的方式
					return { ...node };
				}
				if (node.children) {
					const subtree = this.extractSubtree(node.children, targetId);
					if (subtree) {
						// return this.cloneAndFilterChildren({ ...node, children: [subtree] });可以用这个也可以用下边的方式
						return { ...node, children: [subtree] };
					}
				}
			}
			return null;
		},
		cloneAndFilterChildren(node) {
			if (!node.children || node.children.length === 0) {
				return { ...node, children: [] };
			}
			const filteredChildren = node.children
				.map(child => this.cloneAndFilterChildren(child))
				.filter(child => this.selectedIds.includes(child.id) || child.children.length > 0);
			return { ...node, children: filteredChildren };
		},
		mergeSubtrees(subtrees) {
			this.mergedTree = [];
			const idMap = {};

			for (const subtree of subtrees) {
				this.addSubtreeToMergedTree(this.mergedTree, subtree, idMap);
			}

			return this.mergedTree;
		},
		addSubtreeToMergedTree(mergedTree, subtree, idMap) {
			if (!subtree) return;

			const node = { ...subtree, children: [] };

			if (!idMap[node.id]) {
				idMap[node.id] = node;
				mergedTree.push(node);
			} else {
				// Object.assign(idMap[node.id], node);
			}

			if (subtree.children) {
				for (const child of subtree.children) {
					this.addSubtreeToMergedTree(mergedTree[mergedTree.length-1].children, child, idMap);
				}
			}
		},
		remove(node, data) {
			let keys = [];
			this.getRemovedIds(data,keys);
			keys.map(item => {
				this.selectedIds.splice(this.selectedIds.indexOf(item), 1);
			})
			this.$refs.tree.setCheckedKeys(this.selectedIds);
		},
		getRemovedIds(data,keys) {
			if (data.children && data.children.length > 0) {
				data.children.map(item => {
					this.getRemovedIds(item,keys);
				})
			} else {
				keys.push(data.id);
			}
		},
	}
}

</script>
<style lang="less" scoped>
.flex {
	display: flex;
	justify-content: space-evenly;
}
.tree-row{
	min-width: 200px;
}
.custom-tree-node{
	display: flex;
	flex:1;
	justify-content: space-around;
}
</style>
相关推荐
用户440145493141940 分钟前
Spring Boot 3.x 异步编程实战:从 @Async 到虚拟线程
javascript
卓怡学长1 小时前
w263基于springboot + vue 健康饮食管理系统
java·数据库·vue.js·spring boot·spring·intellij-idea
无情的西瓜皮2 小时前
MCP 协议实战:从零搭建一个 MCP 服务器(Node.js 版)
vue.js·人工智能·typescript·node.js
wangruofeng2 小时前
终端里 rm 一下文件就没了,macOS 怎么删文件才进废纸篓
javascript·命令行·apple
万亿少女的梦1682 小时前
基于Spring Boot、Vue.js和MySQL的超市管理系统设计与实现
java·vue.js·spring boot·mysql·管理系统
小妖6662 小时前
React input 输入卡顿问题
前端·javascript·react.js
李明卫杭州3 小时前
Vue2 portal-target 组件与 Vue3 的针对性优化
前端·javascript·vue.js
你怎么知道我是队长4 小时前
JavaScript的函数介绍
开发语言·前端·javascript
weedsfly5 小时前
观察者模式 vs 发布-订阅模式:从概念到实战,一次讲清楚
前端·javascript·面试
咪饭只吃一小碗5 小时前
告别微调成本!用 RAG 本地向量库解决大模型私有领域数据接入
javascript·后端·面试