Merge pull request #840 from nwind/master

优化 select 在大数据量下的性能
This commit is contained in:
liaoxuezhi 2020-08-11 22:15:10 +08:00 committed by GitHub
commit 216bb2c834
2 changed files with 101 additions and 85 deletions

View File

@ -66,6 +66,7 @@
"react-progress-2": "^4.4.2", "react-progress-2": "^4.4.2",
"react-select": "1.2.1", "react-select": "1.2.1",
"react-textarea-autosize": "5.1.0", "react-textarea-autosize": "5.1.0",
"react-tiny-virtual-list": "^2.2.0",
"react-transition-group": "2.9.0", "react-transition-group": "2.9.0",
"react-visibility-sensor": "3.11.0", "react-visibility-sensor": "3.11.0",
"redux": "^3.7.2", "redux": "^3.7.2",

View File

@ -7,6 +7,7 @@
import {uncontrollable} from 'uncontrollable'; import {uncontrollable} from 'uncontrollable';
import React from 'react'; import React from 'react';
import VirtualList from 'react-tiny-virtual-list';
import Overlay from './Overlay'; import Overlay from './Overlay';
import PopOver from './PopOver'; import PopOver from './PopOver';
import Downshift, {ControllerStateAndHelpers} from 'downshift'; import Downshift, {ControllerStateAndHelpers} from 'downshift';
@ -402,7 +403,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
componentDidUpdate(prevProps: SelectProps) { componentDidUpdate(prevProps: SelectProps) {
const props = this.props; const props = this.props;
let fn:() => void = noop; let fn: () => void = noop;
if ( if (
props.value !== prevProps.value || props.value !== prevProps.value ||
@ -410,17 +411,23 @@ export class Select extends React.Component<SelectProps, SelectState> {
) { ) {
let selection: Array<Option>; let selection: Array<Option>;
if ( if (
( (!prevProps.options || !prevProps.options.length) &&
!prevProps.options props.options.length
|| !prevProps.options.length
)
&& props.options.length
) { ) {
const {selection: stateSelection} = this.state; const {selection: stateSelection} = this.state;
const {multiple, defaultCheckAll, options, onChange, simpleValue} = props; const {
multiple,
defaultCheckAll,
options,
onChange,
simpleValue
} = props;
if (multiple && defaultCheckAll && options.length) { if (multiple && defaultCheckAll && options.length) {
selection = union(options, stateSelection); selection = union(options, stateSelection);
fn = () => onChange(simpleValue ? selection.map(item => item.value) : selection); fn = () =>
onChange(
simpleValue ? selection.map(item => item.value) : selection
);
} else { } else {
selection = value2array(props.value, props); selection = value2array(props.value, props);
} }
@ -428,9 +435,12 @@ export class Select extends React.Component<SelectProps, SelectState> {
selection = value2array(props.value, props); selection = value2array(props.value, props);
} }
this.setState({ this.setState(
selection: selection {
}, fn); selection: selection
},
fn
);
} }
} }
@ -774,83 +784,88 @@ export class Select extends React.Component<SelectProps, SelectState> {
</div> </div>
) : null} ) : null}
{/* todo 当数目比较多的时候会卡顿,需要优化这个滚动。 */}
{filtedOptions.length ? ( {filtedOptions.length ? (
filtedOptions.map((item, index) => { <VirtualList
const checked = height={280}
selectedItem === item || itemCount={filtedOptions.length}
!!~selectionValues.indexOf(item[valueField]); itemSize={35}
renderItem={({index, style}) => {
const item = filtedOptions[index];
const checked =
selectedItem === item ||
!!~selectionValues.indexOf(item[valueField]);
return (
<div
{...getItemProps({
key:
typeof item.value === 'string'
? `${item.label}-${item.value}`
: index,
index,
item,
disabled: item.disabled
})}
style={style}
className={cx(`Select-option`, {
'is-disabled': item.disabled,
'is-highlight': highlightedIndex === index,
'is-active': checked
})}
>
{removable ? (
<a data-tooltip="移除" data-position="left">
<Icon
icon="minus"
className="icon"
onClick={(e: any) => this.handleDeleteClick(e, item)}
/>
</a>
) : null}
{editable ? (
<a data-tooltip="编辑" data-position="left">
<Icon
icon="pencil"
className="icon"
onClick={(e: any) => this.handleEditClick(e, item)}
/>
</a>
) : null}
return ( {checkAll || multiple ? (
<div <Checkbox
{...getItemProps({ checked={checked}
key: trueValue={item.value}
typeof item.value === 'string' onChange={() => {
? `${item.label}-${item.value}` this.handleChange(item);
: index, }}
index, disabled={item.disabled}
item, >
disabled: item.disabled {item.disabled
})} ? item[labelField]
className={cx(`Select-option`, { : highlight(
'is-disabled': item.disabled, item[labelField],
'is-highlight': highlightedIndex === index, inputValue as string,
'is-active': checked cx('Select-option-hl')
})} )}
>
{removable ? (
<a data-tooltip="移除" data-position="left">
<Icon
icon="minus"
className="icon"
onClick={(e: any) => this.handleDeleteClick(e, item)}
/>
</a>
) : null}
{editable ? (
<a data-tooltip="编辑" data-position="left">
<Icon
icon="pencil"
className="icon"
onClick={(e: any) => this.handleEditClick(e, item)}
/>
</a>
) : null}
{checkAll || multiple ? ( {item.tip}
<Checkbox </Checkbox>
checked={checked} ) : (
trueValue={item.value} <span>
onChange={() => { {item.disabled
this.handleChange(item); ? item[labelField]
}} : highlight(
disabled={item.disabled} item[labelField],
> inputValue as string,
{item.disabled cx('Select-option-hl')
? item[labelField] )}
: highlight( {item.tip}
item[labelField], </span>
inputValue as string, )}
cx('Select-option-hl') </div>
)} );
}}
{item.tip} />
</Checkbox>
) : (
<span>
{item.disabled
? item[labelField]
: highlight(
item[labelField],
inputValue as string,
cx('Select-option-hl')
)}
{item.tip}
</span>
)}
</div>
);
})
) : ( ) : (
<div className={cx('Select-noResult')}>{__(noResultsText)}</div> <div className={cx('Select-noResult')}>{__(noResultsText)}</div>
)} )}