组织架构树形控件的实现附带搜索


记录下这次需求的实现过程,实现的效果如下:

  1. 能够正常显示出组织的层级关系
  2. 能模糊搜索出员工

简单画个思维脑图说明接下来该做的事

1. 先要和后端沟通好树形结构的数据结构,因为他是有层级关系的

我们这里模拟的数据如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const mock = [
{
key: 1,
title: "总公司",
children: [
{
key: 2,
title: "总经办",
children: [
{
key: 3,
title: "总经理",
children: [
{ key: 11,title: "张三", userId: 1, jobNumber: "111111" },
{ key: 12,title: "李四", userId: 2, jobNumber: "122222" },
{ key: 123,title: "李四", userId: 24, jobNumber: "3453454" },
]
},
{
key: 4,
title: "总经理",
children: [
{ key: 13,title: "王五", userId: 3, jobNumber: "133333" }
]
},
]
},
{
key: 5,
title: "市场部",
children: []
}
]
}
]
2. 变量声明
1
2
3
4
const [staffData, setStaffData] = useState<any>([]); // 组织架构数据
const [allStaffList, setAllStaffList] = useState<any>([]); // 所有员工集合
const [searchStaffList, setSearchStaffList] = useState<any>([]); // 搜索员工的集合
const [searchVal, setSearchVal] = useState(""); // 搜索value值
3.核心HTML结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<div>
<Input onChange={onChange} placeholder="请输入姓名" prefix={<SearchOutlined />} />
</div>
{
staffData.length > 0 && !searchVal && (
<div className="m-tree-container">
<Tree
blockNode
defaultExpandedKeys={[1]}
autoExpandParent
treeData={staffData}
titleRender={
(nodeData: any) => {
return (
<div>
{
nodeData.userId ? (
<div className="flex">
<p className="flex-1">{nodeData.title}</p>
</div>
) : <p>{nodeData.title}<span>{`(${nodeData?.children?.length || 0})`}</span></p>
}
</div>
)
}
}
/>
</div>
)
}
<div>
{
searchVal
&& (
searchStaffList.length > 0 ? (
searchStaffList.map((item) => {
return (
<div className="h-staff-item">
{item.title}
</div>
)
})
) : <Empty description="未搜索到该员工" />
)
}
</div>
4. 核心js
1
2
3
useEffect(() => {
getStaff(); // 获取组织架构数据
}, [getStaff])
1
2
3
4
const getStaff = useCallback(() => {
setStaffData(mock); // 模拟的数据存入antd Tree组件
handleSaveAllStaff(mock, []); // 取出所有部门的员工,并且存下来
}, [handleSaveAllStaff])
1
2
3
4
5
6
7
8
9
10
11
12
13
// 递归出每个部门的员工
const handleSaveAllStaff = useCallback((data, tempList: {}[]) => {
const staffList: {}[] = tempList;
data.forEach((i) => {
if (i.children && i.children.length > 0) {
return handleSaveAllStaff(i.children, staffList);
}
if (i.userId) {
staffList.push(i);
}
})
setAllStaffList(staffList);
}, [])
1
2
3
4
5
6
7
// input onChange事件
const onChange = useCallback((e) => {
const { value } = e.target;
setSearchVal(value);
const result = allStaffList.filter(i => i.title.includes(value)); // 模糊匹配出员工
result.length > 0 ? setSearchStaffList(result) : setSearchStaffList([]); // 结果反馈
}, [allStaffList])

Tip: includes这个方法可以用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false,我们可以用这个方法来实现模糊匹配的需求。

总结:关键的问题其实就是和后端先沟通好数据结构,需要注意antd Tree组件对应的参数,交互上的一些体验

我的微信公众号: 梨的前端小屋


文章作者: 梨啊梨
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 梨啊梨 !
  目录