antd design TreeSelect 改造
1.背景
对于部门树组件,需要支持三种操作: 点击一次复选框,表示选中当前节点及该节点下的所有子节点;点击二次,表示选中当前节点;点击三次,表示不选中当前节点
2.现状
目前常见的操作:
1.点击复选框时,选中当前节点及该节点下的所有子节点;
2.取消复选框,取消当前节点及该节点下的所有子节点;
3.改造思路
首先把复选框改为不受控,即父节点和子节点不联动。通过treeCheckStrictly属性。
通过onChange事件,去手动控制选中的节点。
- 下面的代码片段,使用了递归算法,找出当前点击的父节点下,没有被选中的子节点及所有子节点
// 获取没有被选中的子节点
getChildNodeType = (children, value, noSelectedChildNode=[], allChildNode=[]) => {
children.forEach((item)=> {
const index = value.findIndex(obj => obj.value === item.props.id)
// 没有选中则添加到没有选中的数组中
index === -1 && (noSelectedChildNode.push({label: item.props.name, value: item.props.id}))
allChildNode.push(item.props.id)
if (item.props.children && item.props.children.length > 0) { // 有孩子节点
this.getChildNodeType(item.props.children, value, noSelectedChildNode, allChildNode)
}
})
return {noSelectedChildNode, allChildNode}
}
-
下面的代码片段讲解:
只拦截点击的是父节点。对叶子节点不予操作点击父节点时,如果子节点没有全部选中,则把没有选中的节点加入到所有选中的节点
再次点击父节点时,需要把所有的子节点从选中的节点中移除掉,并且需要把父节点加入到选中的节点中(父节点就会处于勾选状态)再次点击父节点时,不操作处理,父节点会主动取消勾选状态
handleChange = (value, label, extra) => {
// console.log('handleChangevalue========', value, label, extra)
if (this.props.treeCheckStrictly && extra.triggerNode?.props?.children && extra.triggerNode?.props?.children.length > 0) { // 不是叶子节点
const {noSelectedChildNode: noSelectedNode, allChildNode: allNode} = this.getChildNodeType(extra.triggerNode.props.children, value)
// console.log('noSelectedChildNode=', noSelectedNode, 'allChildNode=', allNode)
if (extra.checked) { // 父节点被选中
if (noSelectedNode.length > 0 ) { // 子节点没有被全部选中,则选中全部子节点
value = [...value, ...noSelectedNode]
}
} else { // 父节点不被选中
if (noSelectedNode.length === 0 ) { // 子节点全部选中 ,则取消所有子节点
value = value.filter(item => !allNode.includes(item.value))
value.push({label: extra.triggerNode.props.name, value: extra.triggerNode.props.id}) // 选中当前父节点
}
}
}
this.setState({ value });
};
作者: 咸鱼翻身