需求点
在一些react项目中,常常有一些需要目录树这种结构,在很多ui组件库中都有实现,但不知道实现的方式,下面可以根据递归组件来实现树的操作
具体实现
- 数据结构定义
可以将组件的数据定义如下,其中key代表当前的节点key; content代表节点的内容;children代表子节点,子节点的数据结构与父节点一致
export type TreeProps = {
key: string;
content: React.ReactNode;
children: TreeProps[];
};
- 实现组件
import { fakeData } from "./constant";
import { TreeProps } from "./type";
import "./tree.css";
const Tree = () => {
return (
<div>
{fakeData.map((item) => {
return <TreeItem item={item} key={item.key} />;
})}
</div>
);
};
const TreeItem = ({ item }: { item: TreeProps }) => {
return (
<div className="tree-item">
<div className="content">{item.content}</div>
{/* 如果子组件存在多个元素,就进行递归调用item子组件,不断渲染其内容 */}
{item.children.length > 0 && (
<>
{item.children.map((child) => {
return <TreeItem item={child} key={child.key} />;
})}
</>
)}
</div>
);
};
export default Tree;
可以看到效果如下
可以看到基本上实现了文件树的结构,下面我们实现反转的功能
下载antd的图标库
npm install --save @ant-design/icons
在TreeItem组件中增加状态控制树的展开与关闭
const TreeItem = ({ item }: { item: TreeProps }) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="tree-item">
<div className="content" onClick={() => setIsOpen(!isOpen)}>
<>
{item.children.length > 0 ? (
<>
{isOpen ? (
<DownOutlined style={styles} />
) : (
<RightOutlined style={styles} />
)}
</>
) : (
<LineOutlined style={styles} />
)}
</>
<div>{item.content}</div>
</div>
{/* 如果子组件存在多个元素,就进行递归调用item子组件,不断渲染其内容 */}
{item.children.length > 0 && isOpen && (
<>
{item.children.map((child) => {
return <TreeItem item={child} key={child.key} />;
})}
</>
)}
</div>
);
};
实现效果
总结
- 使用递归组件的方式实现了树组件,了解其作用原理
- 在子组件内部实现其展开与关闭操作,可以避免在一些组件操作的时候,更新整个组件,提升了一定的性能