Skip to content

Commit 2ea9a0a

Browse files
【下拉组件】分组功能 (#718)
1 parent a0ec627 commit 2ea9a0a

9 files changed

Lines changed: 433 additions & 14 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
order: 2
3+
title: 分组下拉基本使用
4+
desc: 基本使用
5+
---
6+
7+
```jsx
8+
/**
9+
* title: 分组下拉基本使用
10+
* desc: 基本使用
11+
*/
12+
import React, { useState } from 'react';
13+
import { Select } from 'cloud-react';
14+
15+
const Option = Select.Option;
16+
17+
const dataList = [
18+
{
19+
"label":"淘宝",
20+
"value":"taobao",
21+
"options":[
22+
{
23+
"label":"淘宝店",
24+
"value":11
25+
},
26+
{
27+
"label":"天猫店",
28+
"value":10
29+
}
30+
]
31+
},
32+
{
33+
"label":"京东",
34+
"value":"jos",
35+
"options":[
36+
{
37+
"label":"自营店",
38+
"value":20
39+
},
40+
{
41+
"label":"非自营店",
42+
"value":21
43+
}
44+
]
45+
}
46+
];
47+
48+
export default function SelectDemo() {
49+
50+
const [ value, setValue] = useState(20);
51+
const handleChange = (value, prevValue) => {
52+
console.log('select --- ' + value);
53+
console.log('prevSelect --- ' + prevValue);
54+
setValue(value)
55+
};
56+
57+
return (
58+
<div className="demo">
59+
<Select
60+
value={value}
61+
onChange={handleChange}
62+
style={{ width: 120 }}
63+
dataSource={dataList}
64+
/>
65+
</div>
66+
);
67+
}
68+
```
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
order: 2
3+
title: 分组下拉基本使用
4+
desc: 基本使用
5+
---
6+
7+
```jsx
8+
/**
9+
* title: 分组下拉基本使用 - 2
10+
* desc: 基本使用
11+
*/
12+
import React, { useState } from 'react';
13+
import { Select } from 'cloud-react';
14+
15+
const Option = Select.Option;
16+
17+
export default function Group2() {
18+
const handleChange = (value, prevValue) => {
19+
console.log('select --- ' + value);
20+
console.log('prevSelect --- ' + prevValue);
21+
};
22+
23+
return (
24+
<div className="demo">
25+
<Select
26+
defaultValue={'3'}
27+
onChange={handleChange}
28+
style={{ width: 120 }}
29+
>
30+
<Option value="1">单选文字1</Option>
31+
<Option value="2">单选文字2</Option>
32+
<Option type="divider" value="5"/>
33+
<Option value="3">单选文字3</Option>
34+
<Option value="4">单选文字4</Option>
35+
</Select>
36+
</div>
37+
);
38+
}
39+
```
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
order: 2
3+
title: 分组下拉基本使用
4+
desc: 基本使用
5+
---
6+
7+
```jsx
8+
/**
9+
* title: 分组下拉基本使用 - 3
10+
* desc: 添加搜索功能,清空选中项目,部分可选项目不可选中
11+
*/
12+
import React, { useState } from 'react';
13+
import { Select } from 'cloud-react';
14+
15+
const Option = Select.Option;
16+
17+
const dataList = [
18+
{
19+
label: '淘宝',
20+
value: '1',
21+
options: [
22+
{
23+
label: '淘宝(A)',
24+
value: '11',
25+
disabled: true
26+
},{
27+
label: '淘宝(B)',
28+
value: '12',
29+
},{
30+
label: '淘宝(C)',
31+
value: '13'
32+
},
33+
],
34+
},
35+
{
36+
label: '京东',
37+
value: '2',
38+
options: [
39+
{
40+
label: '自营店',
41+
value: '21',
42+
},{
43+
label: '非自营店',
44+
value: '22',
45+
}
46+
],
47+
}
48+
];
49+
50+
export default function SelectDemo() {
51+
const handleChange = (value, prevValue) => {
52+
console.log('select --- ' + value);
53+
console.log('prevSelect --- ' + prevValue);
54+
};
55+
56+
return (
57+
<div className="demo">
58+
<Select
59+
defaultValue={'3'}
60+
onChange={handleChange}
61+
style={{ width: 120 }}
62+
dataSource={dataList}
63+
searchable
64+
allowClear
65+
/>
66+
</div>
67+
);
68+
}
69+
```

src/components/select/index.js

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,33 @@ import { flat, noop } from '@utils';
88
import ContextProvider from '@contexts/context-provider';
99
import SingleSelect from './views/single-select';
1010
import MultiSelect from './views/multi-select';
11+
import GroupSelect from './views/group-select';
1112
import Selected from './views/selected';
1213
import Option from './views/option';
1314
import { selector } from './views/common';
1415

15-
import { formatOptionSource } from './utils';
16+
import { formatOptionSource, isGroupSelectPicker } from './utils';
1617

1718
import './index.less';
1819

19-
const getSelected = (data, children) => {
20+
const getSelected = (data, children, dataSource) => {
2021
const options = Array.isArray(data) ? data : [ data ];
2122
if (!options.length) return [];
22-
const selected = Children.map(children, (child) => {
23-
const { children: label, value } = child.props;
24-
return options.includes(value) ? { label, value } : null;
25-
});
23+
let selected = [];
24+
if (isGroupSelectPicker(dataSource)) {
25+
const groupOptionData = dataSource.map((x) => x.options).flat();
26+
groupOptionData.forEach((x) => {
27+
const { label, value } = x;
28+
if (options.includes(value)) {
29+
selected.push({ label, value });
30+
}
31+
});
32+
} else {
33+
selected = Children.map(children, (child) => {
34+
const { children: label, value } = child.props;
35+
return options.includes(value) ? { label, value } : null;
36+
});
37+
}
2638
return selected;
2739
};
2840

@@ -112,7 +124,7 @@ class Select extends Component {
112124
props.supportLightText,
113125
props.lightTextColor,
114126
);
115-
const selected = getSelected(displayValue, source);
127+
const selected = getSelected(displayValue, source, dataSource);
116128
const emptyValue = multiple ? [] : '';
117129
const currentValue = displayValue !== null ? displayValue : emptyValue;
118130
return {
@@ -220,6 +232,9 @@ class Select extends Component {
220232

221233
if (childs.length) return childs;
222234

235+
if (isGroupSelectPicker(dataSource)) {
236+
return this.getGroupOptions();
237+
}
223238
return getOptions(
224239
dataSource,
225240
labelKey,
@@ -245,6 +260,26 @@ class Select extends Component {
245260
return ele.getBoundingClientRect();
246261
}
247262

263+
getGroupOptions = () => {
264+
const {
265+
dataSource, labelKey, valueKey, isSupportTitle,
266+
} = this.props;
267+
return dataSource.map((group) => {
268+
const groupItem = getOptions(
269+
group.options || [],
270+
labelKey,
271+
valueKey,
272+
isSupportTitle,
273+
);
274+
return (
275+
<div>
276+
<p className="groupName">{group.label}</p>
277+
{groupItem}
278+
</div>
279+
);
280+
});
281+
};
282+
248283
positionPop = () => {
249284
const {
250285
props: { isAppendToBody, position },
@@ -431,7 +466,7 @@ class Select extends Component {
431466
};
432467

433468
renderOptions() {
434-
const { multiple, confirmTemplate } = this.props;
469+
const { multiple, confirmTemplate, dataSource } = this.props;
435470
const { value } = this.state;
436471

437472
if (multiple) {
@@ -450,6 +485,17 @@ class Select extends Component {
450485
);
451486
}
452487

488+
if (isGroupSelectPicker(dataSource)) {
489+
return (
490+
<GroupSelect
491+
{...this.props}
492+
value={value}
493+
dataSource={this.children}
494+
onChange={this.onSimpleOptionChange}
495+
/>
496+
);
497+
}
498+
453499
return (
454500
<SingleSelect
455501
{...this.props}

src/components/select/index.less

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,24 @@
191191
border-radius: 2px;
192192
padding: 8px 0;
193193
background: @color-white;
194+
.divider {
195+
height: 1px;
196+
background: @gray-4;
197+
margin-top: 8px;
198+
margin-bottom: 8px;
199+
}
200+
}
201+
202+
.@{select-prefix-cls}-group-select-options {
203+
.groupName {
204+
color: rgba(0, 0, 0, 0.45);
205+
font-size: 12px;
206+
margin-left: 12px;
207+
margin-bottom: 8px;
208+
&:not(:first-child) {
209+
margin-top: 8px;
210+
}
211+
}
194212
}
195213

196214
.@{select-prefix-cls}-select-options {

src/components/select/index.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@ group:
99
path: /data
1010
---
1111

12-
### 何时使用
12+
## 何时使用
1313

1414
1. 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。
1515
2. 当选项少时(少于 5 项),建议直接将选项平铺,使用 Radio 是更好的选择。
1616

17-
### API
17+
## API
1818
```html
1919
<Select>
2020
<Option value="React">React</Option>
2121
</Select>
2222
```
23+
24+
## Props
2325
### Select Props
2426

2527
| 属性 | 说明 | 类型 | 默认值 |
@@ -73,21 +75,39 @@ group:
7375
| value | 默认使用此属性进行基本操作,选中 option 的值 | string \| number | - |
7476
| item | 当前选项的原始属性,包含 index 值 | object | - |
7577
| className | 该项 option 的类名 | string | - |
78+
| type | type枚举类型: `divider` 表示分割线 | String | '' |
7679

77-
### 代码演示
80+
## 代码演示
7881

82+
### 基础使用
7983
<embed src="@components/select/demos/basic.md" />
8084

85+
### 大小
8186
<embed src="@components/select/demos/sizeSelect.md" />
8287

88+
### 可搜索
8389
<embed src="@components/select/demos/searchable.md" />
8490

91+
### 定制化选项
8592
<embed src="@components/select/demos/customItem.md" />
8693

94+
### 不可用
8795
<embed src="@components/select/demos/disabled.md" />
8896

97+
### 指定使用的键值
8998
<embed src="@components/select/demos/key.md" />
9099

100+
### 触发方式
91101
<embed src="@components/select/demos/trigger.md" />
92102

103+
### 分组
104+
<embed src="@components/select/demos/group.md" />
105+
106+
### 分组 带分割线
107+
<embed src="@components/select/demos/group2.md" />
108+
109+
### 分组可搜索
110+
<embed src="@components/select/demos/groupSearch.md" />
111+
112+
### 多选下拉支持不限
93113
<embed src="@components/select/demos/unlimited.md" />

0 commit comments

Comments
 (0)