forked from p96170835/amis
select 超过 100 行数据时才使用 virtual list,这样就不需要每次都加上滚动条宽度了
This commit is contained in:
parent
dd2b5e0959
commit
40b7f5b60d
|
@ -759,6 +759,84 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
|
||||
const itemHeight = this.state.itemHeight;
|
||||
|
||||
// 渲染单个选项
|
||||
const 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}
|
||||
|
||||
{checkAll || multiple ? (
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
trueValue={item.value}
|
||||
onChange={() => {
|
||||
this.handleChange(item);
|
||||
}}
|
||||
disabled={item.disabled}
|
||||
>
|
||||
{item.disabled
|
||||
? item[labelField]
|
||||
: highlight(
|
||||
item[labelField],
|
||||
inputValue as string,
|
||||
cx('Select-option-hl')
|
||||
)}
|
||||
|
||||
{item.tip}
|
||||
</Checkbox>
|
||||
) : (
|
||||
<span>
|
||||
{item.disabled
|
||||
? item[labelField]
|
||||
: highlight(
|
||||
item[labelField],
|
||||
inputValue as string,
|
||||
cx('Select-option-hl')
|
||||
)}
|
||||
{item.tip}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<div ref={this.menu} className={cx('Select-menu')}>
|
||||
{searchable ? (
|
||||
|
@ -798,89 +876,17 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
</div>
|
||||
|
||||
{filtedOptions.length ? (
|
||||
filtedOptions.length > 100 ? ( // 超过 100 个数据才启用 virtuallist 避免滚动条问题
|
||||
<VirtualList
|
||||
height={
|
||||
filtedOptions.length > 8 ? 280 : filtedOptions.length * itemHeight
|
||||
}
|
||||
itemCount={filtedOptions.length}
|
||||
itemSize={itemHeight}
|
||||
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}
|
||||
|
||||
{checkAll || multiple ? (
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
trueValue={item.value}
|
||||
onChange={() => {
|
||||
this.handleChange(item);
|
||||
}}
|
||||
disabled={item.disabled}
|
||||
>
|
||||
{item.disabled
|
||||
? item[labelField]
|
||||
: highlight(
|
||||
item[labelField],
|
||||
inputValue as string,
|
||||
cx('Select-option-hl')
|
||||
)}
|
||||
|
||||
{item.tip}
|
||||
</Checkbox>
|
||||
) : (
|
||||
<span>
|
||||
{item.disabled
|
||||
? item[labelField]
|
||||
: highlight(
|
||||
item[labelField],
|
||||
inputValue as string,
|
||||
cx('Select-option-hl')
|
||||
)}
|
||||
{item.tip}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
renderItem={renderItem}
|
||||
/>): (
|
||||
filtedOptions.map((item, index) => { return renderItem({index}) })
|
||||
)
|
||||
) : (
|
||||
<div className={cx('Select-noResult')}>{__(noResultsText)}</div>
|
||||
)}
|
||||
|
|
|
@ -177,12 +177,7 @@ export default class VirtualList extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
// 自适应宽度
|
||||
updateRootWidth(isDidUpdate: boolean = false) {
|
||||
let scrollbarWidth =
|
||||
window.innerWidth - document.documentElement.clientWidth || 15;
|
||||
if (isDidUpdate) {
|
||||
scrollbarWidth = 0;
|
||||
}
|
||||
updateRootWidth() {
|
||||
const itemsDom = this.rootNode.children[0].children;
|
||||
const containerWidth = this.rootNode.parentElement!.getBoundingClientRect()
|
||||
.width;
|
||||
|
@ -196,7 +191,7 @@ export default class VirtualList extends React.PureComponent<Props, State> {
|
|||
if (containerWidth >= maxItemWidth) {
|
||||
this.rootNode.style.width = containerWidth + 'px';
|
||||
} else {
|
||||
this.rootNode.style.width = maxItemWidth + scrollbarWidth + 'px';
|
||||
this.rootNode.style.width = maxItemWidth + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +253,7 @@ export default class VirtualList extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
componentDidUpdate(_: Props, prevState: State) {
|
||||
this.updateRootWidth(true);
|
||||
this.updateRootWidth();
|
||||
const {offset, scrollChangeReason} = this.state;
|
||||
if (
|
||||
prevState.offset !== offset &&
|
||||
|
|
Loading…
Reference in New Issue