Skip to content

Commit 1163483

Browse files
author
liyuan-meng
committed
✨[TreeSelect]支持动态加载
1 parent 6772580 commit 1163483

7 files changed

Lines changed: 214 additions & 8 deletions

File tree

src/components/tree-select/const.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,15 @@ export const getNodePath = tree => {
7373
if (!node.path) {
7474
Object.assign(node, { path: [] });
7575
}
76-
node.path.push(node.name);
76+
node.path.push(node?.name);
7777

7878
if (node?.children?.length) {
7979
node.children.forEach(cNode => {
8080
if (!cNode.path) {
8181
Object.assign(cNode, { path: [] });
8282
}
8383
cNode.path.push(...[...parentNodePath, node.name]);
84-
fn(cNode, node.path);
84+
fn(cNode, node?.path);
8585
});
8686
}
8787
};
@@ -95,7 +95,7 @@ export const findTreeNode = (treeNode, treeData = []) => {
9595
if (targetNode) {
9696
return;
9797
}
98-
if (node.id === treeNode.id) {
98+
if (node?.id === treeNode?.id) {
9999
targetNode = node;
100100
}
101101
if (node?.children?.length) {
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
---
2+
order: 2
3+
title: 多层单选与多选
4+
desc: 与Tree结合的树下拉
5+
---
6+
7+
```jsx
8+
import React from 'react';
9+
import { TreeSelect } from 'cloud-react';
10+
11+
const treeData = [
12+
{
13+
id: 1,
14+
name: '所有基础',
15+
pId: null,
16+
disableRemove: true,
17+
disableRename: true,
18+
children: [
19+
{
20+
id: 11,
21+
name: '禁止删除节点',
22+
pId: 1,
23+
disableRemove: true,
24+
children: [],
25+
},
26+
{
27+
id: 12,
28+
name: '禁止新增节点',
29+
pId: 1,
30+
disableAdd: true,
31+
children: [],
32+
},
33+
{
34+
id: 13,
35+
name: '禁止重命名节点',
36+
pId: 1,
37+
disableRename: true,
38+
children: [],
39+
},
40+
{
41+
id: 14,
42+
name: '未分类',
43+
pId: 1,
44+
disableRemove: true,
45+
disableAdd: true,
46+
disableRename: true,
47+
isLeaf: true,
48+
}
49+
]
50+
}
51+
];
52+
53+
function findNodeById(nodeId, data) {
54+
let targetNode = null;
55+
56+
const fn = node => {
57+
if (node?.children?.length) {
58+
node?.children?.forEach(fn);
59+
if (node.id === nodeId) {
60+
targetNode = node;
61+
}
62+
} else {
63+
if (node.id === nodeId) {
64+
targetNode = node;
65+
}
66+
}
67+
};
68+
69+
data.find(fn)
70+
return targetNode;
71+
}
72+
73+
class TreeSelectDemo extends React.Component {
74+
constructor(props) {
75+
super(props);
76+
this.state = {
77+
treeData: JSON.parse(JSON.stringify(treeData)),
78+
treeData1: JSON.parse(JSON.stringify(treeData)),
79+
selectedNodes: [],
80+
singleNodes: []
81+
};
82+
}
83+
84+
onChangeSingle = (node, selectedNodes) => {
85+
this.setState({
86+
singleNodes: selectedNodes
87+
});
88+
};
89+
90+
handleChange = (node, selectedNodes) => {
91+
this.setState({
92+
selectedNodes
93+
});
94+
};
95+
96+
render() {
97+
return (
98+
<div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
99+
<div>
100+
<h5>单选</h5>
101+
<TreeSelect
102+
searchable
103+
searchInBox
104+
allowClear
105+
type="single"
106+
containParentNode
107+
placeholder="选择一个选项"
108+
style={{ width: 420, maxWidth: 420 }}
109+
dropdownStyle={{ maxWidth: 420 }}
110+
dataSource={this.state.treeData}
111+
value={this.state.singleNodes}
112+
onChange={this.onChangeSingle}
113+
isDynamicLoad
114+
onLoadData={(data, node) => {
115+
return new Promise(resolve => {
116+
setTimeout(() => {
117+
node.children = [
118+
{
119+
id: `${node.id}1`,
120+
name: '动态加载一个',
121+
pId: node.id,
122+
level: node.level + 1,
123+
children: [],
124+
},
125+
{
126+
id: `${node.id}2`,
127+
name: '动态加载叶子节点',
128+
pId: node.id,
129+
isLeaf: true,
130+
level: node.level + 1,
131+
children: [],
132+
}
133+
];
134+
135+
// 更新 dataSouce
136+
const targetNode = findNodeById(node.id, this.state.treeData);
137+
targetNode.children = node.children;
138+
139+
resolve(data)
140+
}, 1 * 1000);
141+
})
142+
}}
143+
/>
144+
</div>
145+
<div>
146+
<h5>多选</h5>
147+
<TreeSelect
148+
searchable
149+
searchInBox
150+
allowClear
151+
type="multiple"
152+
containParentNode
153+
placeholder="选择一个选项"
154+
style={{ width: 420, maxWidth: 420 }}
155+
dropdownStyle={{ maxWidth: 420 }}
156+
dataSource={this.state.treeData1}
157+
value={this.state.selectedNodes}
158+
onChange={this.handleChange}
159+
isDynamicLoad
160+
onLoadData={(data, node) => {
161+
return new Promise(resolve => {
162+
setTimeout(() => {
163+
node.children = [
164+
{
165+
id: `${node.id}1`,
166+
name: '动态加载一个',
167+
pId: node.id,
168+
level: node.level + 1,
169+
children: [],
170+
},
171+
{
172+
id: `${node.id}2`,
173+
name: '动态加载叶子节点',
174+
pId: node.id,
175+
isLeaf: true,
176+
level: node.level + 1,
177+
children: [],
178+
}
179+
];
180+
181+
// 更新 dataSouce
182+
const targetNode = findNodeById(node.id, this.state.treeData1);
183+
targetNode.children = node.children;
184+
185+
resolve(data)
186+
}, 1 * 1000);
187+
})
188+
}}
189+
/>
190+
</div>
191+
</div>
192+
);
193+
}
194+
}
195+
196+
export default TreeSelectDemo;
197+
```

src/components/tree-select/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ class TreeSelect extends Component {
380380
allowClear={allowClear}
381381
placeholder={placeholder}
382382
dataSource={value}
383-
treeData={this.state.treeData}
383+
treeData={this.props.isDynamicLoad ? this.props.dataSource : this.state.treeData}
384384
disabled={disabled}
385385
searchable={searchable}
386386
searchInBox={this.props.searchInBox}

src/components/tree-select/index.less

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,11 @@
356356
&-list-container {
357357
padding: 0;
358358
overflow: hidden!important;
359+
360+
.loading-spin {
361+
margin: 0 10px;
362+
top: 1px;
363+
}
359364
}
360365

361366
&-search-input {

src/components/tree-select/index.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ group:
4242
| position | 下拉框定位:`top` `bottom` `auto`(是否启用自动定位,如需使用可设置为`auto`| string | `bottom` |
4343
| dropdownClassName | 下拉框类名 | string | - |
4444
| dropdownStyle | 下拉框样式 | object | {} |
45-
| showPath | 展示路径 | bool | false |
45+
| showPath | 展示路径(和 动态加载数据 isDynamicLoad 无法同时使用) | bool | false |
46+
| onLoadData | 动态加载数据 | Function | - |
47+
| isDynamicLoad | 动态加载数据 | bool | false |
4648

4749
#### `single = true`,单选下拉树时候支持的配置
4850
| 属性 | 说明 | 类型 | 默认值 |
@@ -84,3 +86,5 @@ group:
8486
### 已选展示完整路径
8587
<embed src="@components/tree-select/demos/path.md" />
8688

89+
### 动态加载节点
90+
<embed src="@components/tree-select/demos/dynamicLoad.md" />

src/components/tree-select/multi-search.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ export default function MultiSearch({
7575
return (
7676
<>
7777
{showSelectList.map(item => {
78-
const name = showPath ? item?.path?.join('/') : item.name;
78+
const name = showPath ? item?.path?.join('/') : item?.name;
7979
return (
80-
<span key={item.id} className={`${selector}-multiple-search-item ${disabled && 'disabled'}`}>
80+
<span key={item?.id} className={`${selector}-multiple-search-item ${disabled && 'disabled'}`}>
8181
<span className={`${selector}-multiple-search-item-text`} title={name}>{name}</span>
8282
{!disabled && <Icon type="close" onClick={evt => onItemClose(evt, item)} />}
8383
</span>

src/components/tree-select/selected.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import './index.less';
1212

1313
const getLables = dataSource => {
1414
const source = Array.isArray(dataSource) ? dataSource : [dataSource];
15-
return source.map(item => item.name || item.label).join(',');
15+
return source.map(item => item?.name || item?.label).join(',');
1616
};
1717

1818
const getPath = (nodeList = [], treeData = []) => nodeList.reduce((arr, item) => {

0 commit comments

Comments
 (0)