Skip to content

Commit 942a33d

Browse files
committed
Modified src/ListBox.js
Modified src/ListItem.js Modified src/ListItemGroup.js
1 parent d338a16 commit 942a33d

File tree

3 files changed

+67
-134
lines changed

3 files changed

+67
-134
lines changed

src/ListBox.js

Lines changed: 48 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,25 @@ function copy(data) {
1616
return isArray(data) ? [].concat(data) : data;
1717
}
1818

19+
function getItemsMap(props) {
20+
const { items, valueField, childrenField } = props;
21+
const maps = {};
22+
23+
function toMaps(items) {
24+
items.forEach(item => {
25+
if (item[childrenField] && Array.isArray(item[childrenField])) {
26+
toMaps(item[childrenField]);
27+
} else {
28+
maps[item[valueField]] = item;
29+
}
30+
});
31+
}
32+
33+
toMaps(items);
34+
35+
return maps;
36+
}
37+
1938
export default class ListBox extends React.Component {
2039

2140
static propTypes = {
@@ -29,7 +48,7 @@ export default class ListBox extends React.Component {
2948
labelField: PropTypes.string,
3049
childrenField: PropTypes.string,
3150
items: PropTypes.array,
32-
//itemsMap: PropTypes.object,
51+
itemsMap: PropTypes.object,
3352
defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]),
3453
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]),
3554
emptyLabel: PropTypes.any,
@@ -69,7 +88,8 @@ export default class ListBox extends React.Component {
6988
emptyLabel: 'Not Found',
7089
enableDownUpSelect: true,
7190
fixListBodyHeightOnIE: true,
72-
//items: [],
91+
items: [],
92+
itemsMap: null,
7393
onFocus: noop,
7494
onBlur: noop,
7595
onKeyDown: noop,
@@ -85,12 +105,6 @@ export default class ListBox extends React.Component {
85105
const selectedValue = [];
86106
let value;
87107

88-
// if (!isUndefined(props.value)) {
89-
// value = isArray(props.value) ? props.value : [props.value];
90-
// } else if (!isUndefined(props.defaultValue)) {
91-
// value = isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue];
92-
// }
93-
94108
if (!isUndefined(props.defaultValue)) {
95109
value = isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue];
96110
}
@@ -105,24 +119,28 @@ export default class ListBox extends React.Component {
105119
this._indexValueMap = {};
106120
this._activeIndex = null;
107121

108-
109122
this.state = {
110-
selectedValue,
111-
//items的value=>item对应表
112-
itemsMap: {}
123+
selectedValue
113124
};
114125
}
115126

116127
static getDerivedStateFromProps(nextProps, prevState) {
117128
const value = nextProps.value;
129+
let itemsMap = nextProps.itemsMap || {};
130+
131+
if (!nextProps.itemsMap) {
132+
itemsMap = getItemsMap(nextProps);
133+
}
134+
135+
const newState = {
136+
itemsMap
137+
};
118138

119139
if (!isUndefined(value)) {
120-
return {
121-
selectedValue: isArray(value) ? copy(value) : [value]
122-
};
140+
newState.selectedValue = isArray(value) ? copy(value) : [value];
123141
}
124142

125-
return {};
143+
return newState;
126144
}
127145

128146
componentDidMount() {
@@ -182,14 +200,13 @@ export default class ListBox extends React.Component {
182200

183201
setValue(value) {
184202
const { multiple, onChange } = this.props;
185-
const { selectedValue, itemsMap } = this.state;
203+
const { selectedValue } = this.state;
186204

187205
if (!multiple) {
188206
selectedValue.length = 0;
189207
}
190208

191209
selectedValue.push(value);
192-
193210
if (!('value' in this.props)) {
194211
this.setState({
195212
selectedValue
@@ -209,14 +226,13 @@ export default class ListBox extends React.Component {
209226
}
210227

211228
onItemSelect = (item, el) => {
212-
const valueField = 'value';
229+
const { valueField } = this.props;
213230
this.setValue(item[valueField]);
214231
}
215232

216233
onItemDeselect = (item, el) => {
217-
const { multiple, onChange, labelInValue } = this.props;
234+
const { multiple, onChange, labelInValue, valueField } = this.props;
218235
const { selectedValue } = this.state;
219-
const valueField = 'value';
220236

221237
if (!multiple) return;
222238

@@ -304,31 +320,26 @@ export default class ListBox extends React.Component {
304320

305321
this._activeIndex = list[idx].getAttribute('data-index');
306322
scrollIntoView(list[idx], this.getListViewBody());
307-
//scrollview.scrollIntoView(list[idx]);
308323
} else if (ENTER && activeIndex !== null) {
309324
const value = indexValueMap[activeIndex];
310-
const item = state.itemsMap[value] || {};
325+
const item = state.itemsMap[value];
311326
this.setValue(value);
312327
//触发onItemClick
313-
this.onItemClick({
314-
value,
315-
label: item[props.labelField]
316-
});
328+
this.onItemClick(item);
317329
}
318330

319331
}
320332

321333
renderListItems(items, selectedMap) {
322334
const { labelField, valueField, childrenField, prefixCls, disabled, renderMenuItem, renderMenuGroupTitle } = this.props;
323-
const { itemsMap } = this.state;
324335

325336
return items.map(item => {
326-
if (typeof item === 'string' || typeof item === 'number') {
327-
item = {
328-
[labelField]: item,
329-
[valueField]: item,
330-
}
331-
}
337+
// if (typeof item === 'string' || typeof item === 'number') {
338+
// item = {
339+
// [labelField]: item,
340+
// [valueField]: item,
341+
// }
342+
// }
332343

333344
const isGroup = item[childrenField];
334345
const itemPrefixCls = `${prefixCls}-item`;
@@ -338,7 +349,6 @@ export default class ListBox extends React.Component {
338349
let itemIndex = this._itemIndex++;
339350

340351
if (!isGroup) {
341-
itemsMap[item[valueField]] = item;
342352
this._indexValueMap[itemIndex] = item[valueField];
343353

344354
if (!disabled && !item.disabled) {
@@ -354,7 +364,6 @@ export default class ListBox extends React.Component {
354364
return !isGroup ? (
355365
<ListItem
356366
key={item[valueField]}
357-
value={item[valueField]}
358367
prefixCls={itemPrefixCls}
359368
selected={selectedMap[item[valueField]]}
360369
disabled={disabled || !!item.disabled}
@@ -383,89 +392,22 @@ export default class ListBox extends React.Component {
383392
});
384393
}
385394

386-
renderListChild(children, selectedMap) {
387-
const { labelField, valueField, prefixCls, disabled } = this.props;
388-
const { itemsMap } = this.state;
389-
390-
const itemPrefixCls = `${prefixCls}-item`;
391-
const activeCls = `${prefixCls}-item-active`;
392-
393-
return React.Children.map(children, child => {
394-
const props = child.props;
395-
396-
if (child.type.isListItemGroup) {
397-
return React.cloneElement(
398-
child,
399-
{
400-
prefixCls: `${itemPrefixCls}-group`
401-
},
402-
this.renderListChild(props.children, selectedMap)
403-
);
404-
}
405-
406-
let onMouseEnter = noop;
407-
let onMouseLeave = noop;
408-
let itemIndex = this._itemIndex++;
409-
410-
itemsMap[props[valueField]] = Object.assign(
411-
{},
412-
omit(props, ['children', 'selected', 'prefixCls']),
413-
{ [labelField]: props.children }
414-
);
415-
this._indexValueMap[itemIndex] = props[valueField];
416-
417-
if (!props.disabled && !disabled) {
418-
onMouseEnter = e => {
419-
addClass(e.currentTarget, activeCls);
420-
if (props.onMouseEnter) props.onMouseEnter(e);
421-
}
422-
onMouseLeave = e => {
423-
removeClass(e.currentTarget, activeCls);
424-
if (props.onMouseLeave) props.onMouseLeave(e);
425-
}
426-
}
427-
428-
const newProps = {
429-
selected: selectedMap[props[valueField]],
430-
prefixCls: itemPrefixCls,
431-
'data-index': itemIndex,
432-
onClick: this.onItemClick,
433-
onSelect: this.onItemSelect,
434-
onDeselect: this.onItemDeselect,
435-
onMouseEnter,
436-
onMouseLeave,
437-
};
438-
439-
if (disabled) {
440-
newProps.disabled = true;
441-
}
442-
443-
return React.cloneElement(child, newProps);
444-
});
445-
}
446-
447395
renderList() {
448-
const { labelField, valueField, prefixCls, multiple, items, emptyLabel, children } = this.props;
396+
const { items, emptyLabel } = this.props;
449397
const { selectedValue } = this.state;
450398

451-
this.state.itemsMap = {};
452-
453399
const selectedMap = {};
454400
selectedValue.forEach(v => selectedMap[v] = true);
455401

456402
this._itemIndex = 0;
457403
this._indexValueMap = {};
458404
this._activeIndex = null;
459405

460-
if (items && !items.length && !React.Children.count(children)) {
406+
if (items && !items.length) {
461407
return emptyLabel;
462408
}
463409

464-
const childs = Array.isArray(items) ?
465-
this.renderListItems(items, selectedMap) :
466-
this.renderListChild(children, selectedMap);
467-
468-
return React.Children.count(childs) ? childs : emptyLabel;
410+
return this.renderListItems(items, selectedMap);
469411
}
470412

471413
saveListView = (node) => {

src/ListItem.js

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,72 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33
import classNames from 'classnames';
44
import shallowEqual from 'shallowequal';
5-
import omit from 'object.omit';
65

76
export default class ListItem extends React.Component {
87

98
static propTypes = {
109
prefixCls: PropTypes.string,
11-
value: PropTypes.any,
1210
onSelect: PropTypes.func,
1311
onDeselect: PropTypes.func,
1412
onClick: PropTypes.func,
13+
onMouseEnter: PropTypes.func,
14+
onMouseLeave: PropTypes.func,
1515
selected: PropTypes.bool,
1616
disabled: PropTypes.bool,
1717
item: PropTypes.object,
1818
}
1919

2020
static defaultProps = {
2121
prefixCls: 'rw-listbox-item',
22-
value: '',
2322
selected: false,
2423
disabled: false,
2524
}
2625

2726
static isListItem = true;
2827

29-
shouldComponentUpdate(nextProps, nextState, nextContext) {
28+
shouldComponentUpdate(nextProps, nextState) {
3029
return !shallowEqual(this.props, nextProps) ||
3130
!shallowEqual(this.state, nextState);
3231
}
3332

3433
handleItemClick = (e) => {
35-
const { onSelect, onDeselect, onClick, selected, disabled, value, children, item } = this.props;
34+
const { onSelect, onDeselect, onClick, selected, disabled, item } = this.props;
35+
const itemDOM = this.getItemDOM();
3636
if (disabled) return;
3737

38-
const newItem = item || {
39-
value,
40-
label: children
41-
};
42-
4338
if (onClick) {
44-
onClick(newItem, e);
39+
onClick(item, e);
4540
}
4641

4742
if (!selected) {
48-
onSelect && onSelect(newItem, this.refs.item)
43+
onSelect && onSelect(item, itemDOM)
4944
} else {
50-
onDeselect && onDeselect(newItem, this.refs.item)
45+
onDeselect && onDeselect(item, itemDOM)
5146
}
5247
}
5348

54-
saveItem = (item) => {
55-
this.node = item;
49+
saveItem = (dom) => {
50+
this.node = dom;
51+
}
52+
53+
getItemDOM() {
54+
return this.node;
5655
}
5756

5857
render() {
59-
const { prefixCls, disabled, selected, active, children } = this.props;
58+
const { prefixCls, disabled, selected, children, onMouseEnter, onMouseLeave } = this.props;
6059
const classes = classNames({
6160
[`${prefixCls}`]: true,
6261
[`${prefixCls}-selected`]: selected,
6362
[`${prefixCls}-disabled`]: disabled,
6463
});
6564

66-
const others = omit(this.props, Object.keys(ListItem.propTypes));
67-
6865
return <div
69-
{...others}
7066
ref={this.saveItem}
7167
className={classes}
7268
onClick={this.handleItemClick}
69+
onMouseEnter={onMouseEnter}
70+
onMouseLeave={onMouseLeave}
7371
>
7472
{children}
7573
</div>;

0 commit comments

Comments
 (0)