实现的功能,上面有个选择框,当选中全部时,下方树被全选
代码:
<template><div><el-select v-model="selectAll" style="margin-bottom: 10px;" @change="handleSelectAllChange"><el-option value="all" label="全部">全部</el-option><el-option value="one" label="取消">取消</el-option></el-select><el-tree ref="treeRef" class="filter-tree" :data="treeData" :props="defaultProps" node-key=id highlight-current:current-node-key="leafNode.id" @node-click="treeNodeClick" default-expand-all show-checkbox @check="check":default-checked-keys="checKay" /><!-- 设置 check-strictly="true" 表明你希望节点之间的选择状态是独立的,用户可以单独选择每个节点而不影响其他节点的选中状态。这与全选或取消其下一级层级的功能是相符合的,因为这意味着用户可以选择父节点而不会影响其子节点的选中状态。--></div></template><script setup>
import { ref } from "@vue/reactivity";
import { nextTick, watch } from "@vue/runtime-core";
import { ElTree } from "element-plus";
const { proxy } = getCurrentInstance();
const emit = defineEmits(["treeNodeClick"]);const treeData = ref([{children: [{ id: "1", label: "朝阳区", nodeType: 2 }],id: "2", label: "北京市", nodeType: 1
},
{children: [{children: [{ id: "3", label: "高新区", nodeType: 3 },{ id: "5", label: "历下区", nodeType: 3 }],id: "4", label: "济南市", nodeType: 2}],id: "6", label: "山东省", nodeType: 1
},
{children: [{children: [{ id: "7", label: "长安区", nodeType: 3 }],id: "8", label: "石家庄", nodeType: 2}],id: "9", label: "河北省", nodeType: 1
},
{children: [{children: [{ id: "10", label: "中原区", nodeType: 3 }],id: "11", label: "郑州", nodeType: 2},{children: [{ id: "12", label: "老城区", nodeType: 3 }],id: "13", label: "洛阳", nodeType: 2}],id: "14", label: "河南省", nodeType: 1
},
])const treeRef = ref(null);
const selectAll = ref(""); // 使用字符串类型的变量表示选择全部的状态
const defaultProps = {children: 'children',label: 'label',
};
const checKay = ref([])const leafNode = ref({});
const check = (node, checked) => {if (checked) {// 选中节点console.log(node, checked);leafNode.value = node;} else {// 取消选中节点if (node.id === leafNode.value.id) {leafNode.value = {};}}
};
const treeNodeClick = (node) => {emit("treeNodeClick", node);
};
const handleSelectAllChange = (value) => {if (value == "all") {checKay.value = getAllIds(treeData.value)} else {// 如果取消选择全部,则遍历树节点并取消选中所有节点checKay.value = []nextTick(() => {treeRef.value.setCheckedKeys([]);});}
};
// 递归函数,获取所有节点的 id
const getAllIds = (nodes) => {let ids = [];nodes.forEach((node) => {ids.push(node.id);if (node.children) {ids = [...ids, ...getAllIds(node.children)];}});return ids;
};// 递归函数,取消选中所有节点
const deselectAllNodes = (nodes) => {nodes.forEach((node) => {node.checkedKeys = [];if (node.children) {deselectAllNodes(node.children);}});
};
</script>
<style scoped>
.filter-tree {/* margin-top: 10px; */
}
</style>
实现效果:
具体代码剖析:
A、html部分
<el-tree ref="treeRef"
class="filter-tree"
:data="treeData"
:props="defaultProps"node-key=id highlight-current:current-node-key="leafNode.id"@node-click="treeNodeClick"
default-expand-all
show-checkbox@check="check":default-checked-keys="checKay" />
1、ref="treeRef":给 <el-tree> 组件设置一个引用名,可以在 JavaScript 中通过这个引用名来操作该组件。
2、:data="treeData":将 treeData 绑定到 <el-tree> 的 data 属性上,这个属性是树形结构的数据源,用于渲染树节点。
3、:props="defaultProps":将 defaultProps 绑定到 <el-tree> 的 props 属性上,这个属性用于指定树节点的一些属性配置,比如子节点的键名和显示内容的键名。
4、node-key="id":指定树节点数据中用作节点唯一标识的字段名。
5、highlight-current:当节点被选中时,高亮显示该节点。
6、:current-node-key="leafNode.id":设置当前被选中的节点的 key,通常用于在树中显示当前选中的节点。
7、@node-click="treeNodeClick":当点击树节点时触发 treeNodeClick 方法。
8、default-expand-all:默认展开所有的树节点。
9、show-checkbox:显示复选框,允许用户通过复选框选择树节点。
10、@check="check":当复选框状态发生变化时触发 check 方法。
11、:default-checked-keys="checKay":将 checKay 绑定到 <el-tree> 的 default-checked-keys 属性上,用于设置默认选中的节点的 key。
B、js部分
通过官网告诉我们的方法,我们点击节点,打印我们可以发现,选中的时候是放到这个数组里面的
const check = (node, checked) => {if (checked) {// 选中节点console.log(node, checked);leafNode.value = node;} else {// 取消选中节点if (node.id === leafNode.value.id) {leafNode.value = {};}}
};
我们知道default-checked-keys是树结构默认勾选的数组
const checKay = ref([])这个是我定义的默认勾选的数组
当我的选择框为全部 的时候,我只需要把树结构default-checked-keys存放的为全部数据的id即可
const handleSelectAllChange = (value) => {if (value == "all") {checKay.value = getAllIds(treeData.value)} else {// 如果取消选择全部,则遍历树节点并取消选中所有节点checKay.value = []nextTick(() => {treeRef.value.setCheckedKeys([]);});}
};
// 递归函数,获取所有节点的 id
const getAllIds = (nodes) => {let ids = [];nodes.forEach((node) => {ids.push(node.id);if (node.children) {ids = [...ids, ...getAllIds(node.children)];}});r
当不为全部的时候,树全部不选,其实就是将这个数组给清空 就行了
checKay.value = []
我直接写,发现,树并没有取消勾选,
这时候需要首先清空 checKay.value
,然后使用 nextTick
方法等待下一个 DOM 更新周期,并在其中调用 treeRef.value.setCheckedKeys([])
来清空树节点的选中状态
checKay.value = []nextTick(() => {treeRef.value.setCheckedKeys([]);});