Skip to content

Commit

Permalink
perf: virtual list
Browse files Browse the repository at this point in the history
  • Loading branch information
tangjinzhou committed Dec 23, 2021
1 parent 7aae6f6 commit 4e70c6d
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 114 deletions.
164 changes: 87 additions & 77 deletions components/vc-select/OptionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { isValidElement } from '../_util/props-util';
import createRef from '../_util/createRef';
import type { PropType } from 'vue';
import { computed, defineComponent, nextTick, reactive, watch } from 'vue';
import List from '../vc-virtual-list/List';
import List from '../vc-virtual-list';
import type {
OptionsType as SelectOptionsType,
OptionData,
Expand Down Expand Up @@ -346,85 +346,95 @@ const OptionList = defineComponent<OptionListProps<SelectOptionsType[number]>, {
onScroll={onScroll}
virtual={virtual}
onMouseenter={onMouseenter}
children={({ group, groupOption, data, label, value }, itemIndex) => {
const { key } = data;
// Group
if (group) {
return (
<div class={classNames(itemPrefixCls, `${itemPrefixCls}-group`)}>
{renderOption ? renderOption(data) : label !== undefined ? label : key}
</div>
);
}

const { disabled, title, children, style, class: cls, className, ...otherProps } = data;
const passedProps = omit(otherProps, omitFieldNameList);
// Option
const selected = values.has(value);

const optionPrefixCls = `${itemPrefixCls}-option`;
const optionClassName = classNames(itemPrefixCls, optionPrefixCls, cls, className, {
[`${optionPrefixCls}-grouped`]: groupOption,
[`${optionPrefixCls}-active`]: activeIndex === itemIndex && !disabled,
[`${optionPrefixCls}-disabled`]: disabled,
[`${optionPrefixCls}-selected`]: selected,
});

const mergedLabel = childrenAsData ? children : label;

const iconVisible =
!menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected;
v-slots={{
default: ({ group, groupOption, data, label, value }, itemIndex) => {
const { key } = data;
// Group
if (group) {
return (
<div class={classNames(itemPrefixCls, `${itemPrefixCls}-group`)}>
{renderOption ? renderOption(data) : label !== undefined ? label : key}
</div>
);
}

const content = mergedLabel || value;
// https://github.com/ant-design/ant-design/issues/26717
let optionTitle =
typeof content === 'string' || typeof content === 'number'
? content.toString()
: undefined;
if (title !== undefined) {
optionTitle = title;
}
const {
disabled,
title,
children,
style,
class: cls,
className,
...otherProps
} = data;
const passedProps = omit(otherProps, omitFieldNameList);
// Option
const selected = values.has(value);

const optionPrefixCls = `${itemPrefixCls}-option`;
const optionClassName = classNames(itemPrefixCls, optionPrefixCls, cls, className, {
[`${optionPrefixCls}-grouped`]: groupOption,
[`${optionPrefixCls}-active`]: activeIndex === itemIndex && !disabled,
[`${optionPrefixCls}-disabled`]: disabled,
[`${optionPrefixCls}-selected`]: selected,
});

const mergedLabel = childrenAsData ? children : label;

const iconVisible =
!menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected;

const content = mergedLabel || value;
// https://github.com/ant-design/ant-design/issues/26717
let optionTitle =
typeof content === 'string' || typeof content === 'number'
? content.toString()
: undefined;
if (title !== undefined) {
optionTitle = title;
}

return (
<div
{...passedProps}
aria-selected={selected}
class={optionClassName}
title={optionTitle}
onMousemove={e => {
if (otherProps.onMousemove) {
otherProps.onMousemove(e);
}
if (activeIndex === itemIndex || disabled) {
return;
}
setActive(itemIndex);
}}
onClick={e => {
if (!disabled) {
onSelectValue(value);
}
if (otherProps.onClick) {
otherProps.onClick(e);
}
}}
style={style}
>
<div class={`${optionPrefixCls}-content`}>
{renderOption ? renderOption(data) : content}
return (
<div
{...passedProps}
aria-selected={selected}
class={optionClassName}
title={optionTitle}
onMousemove={e => {
if (otherProps.onMousemove) {
otherProps.onMousemove(e);
}
if (activeIndex === itemIndex || disabled) {
return;
}
setActive(itemIndex);
}}
onClick={e => {
if (!disabled) {
onSelectValue(value);
}
if (otherProps.onClick) {
otherProps.onClick(e);
}
}}
style={style}
>
<div class={`${optionPrefixCls}-content`}>
{renderOption ? renderOption(data) : content}
</div>
{isValidElement(menuItemSelectedIcon) || selected}
{iconVisible && (
<TransBtn
class={`${itemPrefixCls}-option-state`}
customizeIcon={menuItemSelectedIcon}
customizeIconProps={{ isSelected: selected }}
>
{selected ? '✓' : null}
</TransBtn>
)}
</div>
{isValidElement(menuItemSelectedIcon) || selected}
{iconVisible && (
<TransBtn
class={`${itemPrefixCls}-option-state`}
customizeIcon={menuItemSelectedIcon}
customizeIconProps={{ isSelected: selected }}
>
{selected ? '✓' : null}
</TransBtn>
)}
</div>
);
);
},
}}
></List>
</>
Expand Down
73 changes: 37 additions & 36 deletions components/vc-tree/NodeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,42 +269,43 @@ export default defineComponent({
itemHeight={itemHeight}
prefixCls={`${prefixCls}-list`}
ref={listRef}
children={(treeNode: FlattenNode) => {
const {
pos,
data: { ...restProps },
title,
key,
isStart,
isEnd,
} = treeNode;
const mergedKey = getKey(key, pos);
delete restProps.key;
delete restProps.children;

const treeNodeProps = getTreeNodeProps(mergedKey, treeNodeRequiredProps);

return (
<MotionTreeNode
{...restProps}
{...treeNodeProps}
title={title}
active={!!activeItem && key === activeItem.key}
pos={pos}
data={treeNode.data}
isStart={isStart}
isEnd={isEnd}
motion={motion}
motionNodes={key === MOTION_KEY ? transitionRange.value : null}
motionType={motionType.value}
onMotionStart={onListChangeStart}
onMotionEnd={onMotionEnd}
treeNodeRequiredProps={treeNodeRequiredProps}
onMousemove={() => {
onActiveChange(null);
}}
/>
);
v-slots={{
default: (treeNode: FlattenNode) => {
const {
pos,
data: { ...restProps },
title,
key,
isStart,
isEnd,
} = treeNode;
const mergedKey = getKey(key, pos);
delete restProps.key;
delete restProps.children;

const treeNodeProps = getTreeNodeProps(mergedKey, treeNodeRequiredProps);
return (
<MotionTreeNode
{...restProps}
{...treeNodeProps}
title={title}
active={!!activeItem && key === activeItem.key}
pos={pos}
data={treeNode.data}
isStart={isStart}
isEnd={isEnd}
motion={motion}
motionNodes={key === MOTION_KEY ? transitionRange.value : null}
motionType={motionType.value}
onMotionStart={onListChangeStart}
onMotionEnd={onMotionEnd}
treeNodeRequiredProps={treeNodeRequiredProps}
onMousemove={() => {
onActiveChange(null);
}}
/>
);
},
}}
></VirtualList>
</>
Expand Down
2 changes: 1 addition & 1 deletion components/vc-virtual-list/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ const List = defineComponent({
virtual,
component: Component = 'div',
onScroll,
children,
children = this.$slots.default,
style,
class: className,
...restProps
Expand Down

0 comments on commit 4e70c6d

Please sign in to comment.