在使用 el-tree 组件时,初始有一份完整的数据和已选中的数据,经过一系列操作后,需要知道:
- 用户最终选择了哪些数据(最终选中项)
- 用户取消了哪些数据(最终未选中项)
- 用户新增了哪些数据(新选中项 = 之前没选,现在选了)
- 用户删除了哪些数据(删除项 = 之前选,现在没选了)
场景举例:
- 初始化时:所有数据 allData,已选数据 selectedData
- 用户操作后:最终选中数据 finalSelectedData
你要:
- 新增项:finalSelectedData 相比于 selectedData 增加了什么
- 删除项:selectedData 相比于 finalSelectedData 少了什么
如何实现
- 初始化时记录已选数据(比如用 selectedData 数组存放每个节点的 id)
- 操作后记录最终选中数据(比如用 finalSelectedData 数组存放每个节点的 id)
- 计算新增和删除数据:
js
// setA - setB:A里有但B里没有
function arrayDiff(arrA, arrB) {
return arrA.filter(item => !arrB.includes(item));
}
const addData = arrayDiff(finalSelectedData, selectedData); // 新增:最终选中但原来没选
const deleteData = arrayDiff(selectedData, finalSelectedData); // 删除:原来有但最终没选
el-tree 获取选中节点
一般你会用 this.$refs.tree.getCheckedKeys()
获取当前选中的节点 id 数组。
js
// 初始化
const selectedData = [1, 2, 3]; // 初始已选 id
// 用户操作后
const finalSelectedData = this.$refs.tree.getCheckedKeys(); // 最终已选 id
// 计算
const addData = arrayDiff(finalSelectedData, selectedData);
const deleteData = arrayDiff(selectedData, finalSelectedData);
提交接口时
- 新增项 addData 用于调用 add_data 接口
- 删除项 deleteData 用于调用 delete_data 接口
示例代码
下面是 Ant Design Vue 的 Tree 组件实现,包含:
- 显示所有树节点并初始化已选中
- 用户操作后,计算新增和删除项
- 提交时分别调用
add_data
和delete_data
接口
假设你用的是 Vue 3 和 ant-design-vue@4.x。
vue
<template>
<div>
<a-tree
checkable
:tree-data="treeData"
:checked-keys="checkedKeys"
@check="onCheck"
defaultExpandAll
/>
<a-button type="primary" @click="handleSubmit" style="margin-top: 16px">
提交变更
</a-button>
<div style="margin-top: 16px">
<b>当前选中节点:</b> {{ checkedKeys.join(', ') }}
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { message } from "ant-design-vue";
// 所有树节点
const treeData = [
{
title: "Node1",
key: "0-0",
children: [
{ title: "Node1-1", key: "0-0-1" },
{ title: "Node1-2", key: "0-0-2" }
]
},
{
title: "Node2",
key: "0-1",
children: [
{ title: "Node2-1", key: "0-1-1" }
]
}
];
// 初始化已选中节点 key
const initialCheckedKeys = ["0-0-1", "0-1-1"];
const checkedKeys = ref([...initialCheckedKeys]); // 当前选中
const initialCheckedKeysRef = ref([...initialCheckedKeys]); // 用ref保存初始
// 选中变化
function onCheck(checkedKeysValue) {
checkedKeys.value = checkedKeysValue;
}
// 计算数组差集
function arrayDiff(arrA, arrB) {
return arrA.filter((item) => !arrB.includes(item));
}
// 提交接口
async function handleSubmit() {
const addData = arrayDiff(checkedKeys.value, initialCheckedKeysRef.value);
const deleteData = arrayDiff(initialCheckedKeysRef.value, checkedKeys.value);
try {
if (addData.length > 0) {
await fetch("/api/add_data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ keys: addData })
});
message.success("新增节点已提交:" + addData.join(", "));
}
if (deleteData.length > 0) {
await fetch("/api/delete_data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ keys: deleteData })
});
message.success("删除节点已提交:" + deleteData.join(", "));
}
if (addData.length === 0 && deleteData.length === 0) {
message.info("没有变更,无需提交。");
}
} catch (e) {
message.error("接口调用失败!");
}
}
</script>
使用方法
-
安装依赖
bashnpm install ant-design-vue
-
在
main.js
里全局引入组件库(如未做过):jsimport Antd from 'ant-design-vue' import 'ant-design-vue/dist/antd.css' app.use(Antd)
-
将上面代码保存为
AntdTreeExample.vue
,并在你的页面引用即可。 -
修改接口地址
/api/add_data
和/api/delete_data
为你的实际接口。