需求
antd多个Tree实现点击一个 Tree 组件的叶子节点后,其他所有 Tree 组件的节点选中状态都被清除
思路
- Tree组件的选中状态可以由selectedKeys属性控制,这是核心
- 其他所有 Tree 组件的节点选中状态都被清除,那么如何判断当前选中的是哪个Tree是关键
实现
- 创建
currentSelectedKeys:这个状态用于记录当前选中的节点的key值。每当点击一个叶子节点时,我们会将当前节点的key值记录在这个状态中,以便在每个 Tree 组件的selectedKeys属性中正确设置选中状态。这样做可以确保只有一个 Tree 组件的节点处于选中状态。 - 创建
activeTreeIndex:这个状态用于记录当前活动的 Tree 组件的索引。每当点击一个 Tree 的节点时,我们会根据点击的节点信息确定当前活动的 Tree 组件的索引,以便后续在设置选中状态时只对当前活动的 Tree 组件进行操作,从而避免干扰其他 Tree 组件的状态。 - 当触发onSelect事件后,首先根据点击的节点信息找到当前活动的 Tree 组件的索引,并将其记录在
activeTreeIndex中。然后,我们判断点击的节点是否是叶子节点,如果是叶子节点,则将当前节点的key值记录在currentSelectedKeys中。
这样,在每个 Tree 组件的 selectedKeys 属性中,我们根据 activeTreeIndex 来判断是否应该设置选中状态。只有当前活动的 Tree 组件的节点会显示选中状态,其他 Tree 组件会被清除选中状态,从而实现需求。
组件代码
import { Tree } from 'antd';
import type { TreeProps } from 'antd/es/tree';
import React from 'react';
import styles from './index.less';
import './antd.less';
import { Key } from 'rc-tree/lib/interface';
interface IProps {
title?: string;
children?: React.ReactNode;
onSelect: (selectedKeys: Key[], info: object, el?: object) => void;
treeData?: any[];
treeDataArr?: any[];
}
const DatasourceTree: React.FC<IProps> = (props) => {
const { children, title, onSelect, treeData, treeDataArr } = props;
const [currentSelectedKeys, setCurrentSelectedKeys] = React.useState<React.Key[]>([]);
const [activeTreeIndex, setActiveTreeIndex] = React.useState<number | null>(null);
const handleSelect: TreeProps['onSelect'] = (selectedKeys: React.Key[], info: any) => {
const selectedNode = info.node;
if (!selectedNode.children || selectedNode.children.length) {
onSelect(selectedKeys, info);
}
};
const handleSelect2: any = (selectedKeys: React.Key[], info: any, el: any) => {
setActiveTreeIndex((treeDataArr as any[]).findIndex((item: any) => item === el));
const selectedNode = info.node;
if (!selectedNode.children || !selectedNode.children.length) {
setCurrentSelectedKeys(selectedKeys);
onSelect(selectedKeys, info, el);
}
};
const { TreeNode } = Tree
const renderTreeNodes = (data: any) => {
return data.map((item: any) => {
if (item.children.length) {
return (
<TreeNode title={item.name} key={item.id} selectable={false}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode title={item.name} key={item.id} />;
});
};
return (
<div className={styles.treeLayoutContainer}>
<div className={styles.treeContainer}>
{treeData && treeData.length && !treeDataArr ? (
<>
<div className={styles.treeTitle}>{title}</div>
<Tree
defaultExpandAll
onSelect={handleSelect}
>
{renderTreeNodes(treeData)}
</Tree>
</>
) : null}
{!treeData && treeDataArr && treeDataArr.length &&
treeDataArr.map((el: any, index: number) => (
<div key={index}>
<div className={styles.treeTitle}>{el.title}</div>
<Tree
defaultExpandAll
onSelect={(selectedKeys: Key[], info: any) => handleSelect2(selectedKeys, info, el)}
selectedKeys={index === activeTreeIndex ? currentSelectedKeys : []}
>
{renderTreeNodes(el.treeData)}
</Tree>
</div>
))
}
</div>
<div style={{ width: '100%', marginLeft: '16px' }}>{children}</div>
</div>
);
};
DatasourceTree.defaultProps = {
title: '数据源管理',
};
export default DatasourceTree;