背景
最近公司所做的项目中有个文档管理的需求,需要有个目录来展示不同的文档。可以对文档目录进行添加、重命名、删除、切换等操作。但是antd的tree组件不能完全满足需要,于是就进行了二次封装。
先看看效果图:
难点
主要的难点是这个hover按钮,之前没什么思路。后来想一想,可以放在数据中的title里面,antd中的数据都可以将一段jsx放进去。如下:
const TreeTitle = (props) => {
const { title, id } = props;
return (
<React.Fragment>
<span>{title}</span>
{id === 'root' ? null : (
<Popover
content={<PopoverContent id={id} title={title} />}
placement="rightTop"
>
<MoreOutlined className="icon-operate" />
</Popover>
)}
</React.Fragment>
);
};
这里的root要注意一下,上面的效果图中的所有类别的id就是root,这是我手动添加到类别数组中的,不是后端返回的,所以不需要hover图标,才加了上面这一层处理。
然后用了递归生成目录树所需的数据结构,如下:
// 加工后端返回的treedata,给title加上hover显示图标
const gernerateTreeData = (data) => {
data = data.map((item) => {
if (item.children && item.children.length) {
return {
key: item.key,
title: <TreeTitle title={item.title} id={item.key} />,
children: gernerateTreeData(item.children),
};
} else {
return {
key: item.key,
title: <TreeTitle title={item.title} id={item.key} />,
};
}
});
return data;
};
html部分就比较简单,如下:
<div style={{ height: '100%', paddingTop: '20px' }}>
<Row justify="space-between">
<Input
prefix={<SearchOutlined style={{ color: '#ddd' }} />}
style={{ marginLeft: '10px', marginBottom: '10px', width: '120px' }}
size="small"
allowClear
onChange={this.handleSearch}
/>
<Button
style={{ marginRight: '5px' }}
size="small"
onClick={() => this.showAddConfirm('add')}
disabled={this.state.isEditing}
>
<PlusOutlined />
</Button>
</Row>
{this.state.treeData.length ? (
<DirectoryTree
style={{ marginLeft: '8px' }}
treeData={gernerateTreeData(this.state.treeData)}
showIcon={false}
expandedKeys={this.state.expandedKeys}
onExpand={this.expand}
switcherIcon={<DownOutlined />}
onSelect={this.select}
></DirectoryTree>
) : null}
</div>
最终效果还是不错的,达到了业务的要求。完美! 洗洗睡。