perf: transfer

pull/6263/head^2
tangjinzhou 2023-02-13 20:46:02 +08:00
parent 68d295d7ef
commit 4ccb1c3e19
4 changed files with 49 additions and 30 deletions

View File

@ -0,0 +1,17 @@
export const groupKeysMap = (keys: string[]) => {
const map = new Map<string, number>();
keys.forEach((key, index) => {
map.set(key, index);
});
return map;
};
export const groupDisabledKeysMap = <RecordType extends any[]>(dataSource: RecordType) => {
const map = new Map<string, number>();
dataSource.forEach(({ disabled, key }, index) => {
if (disabled) {
map.set(key, index);
}
});
return map;
};

View File

@ -76,10 +76,7 @@ const ListBody = defineComponent({
const maxPageCount = Math.ceil(
props.filteredRenderItems.length / mergedPagination.value.pageSize,
);
if (current.value > maxPageCount) {
current.value = maxPageCount;
}
current.value = Math.min(current.value, maxPageCount);
}
},
{ immediate: true },

View File

@ -24,7 +24,7 @@ import { FormItemInputContext, useInjectFormItemContext } from '../form/FormItem
import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
import type { InputStatus } from '../_util/statusUtils';
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
import { groupKeysMap, groupDisabledKeysMap } from '../_util/transKeys';
// CSSINJS
import useStyle from './style';
@ -64,17 +64,17 @@ export type SelectAllLabel =
| ((info: { selectedCount: number; totalCount: number }) => VueNode);
export interface TransferLocale {
titles: VueNode[];
titles?: VueNode[];
notFoundContent?: VueNode;
searchPlaceholder: string;
itemUnit: string;
itemsUnit: string;
remove: string;
selectAll: string;
selectCurrent: string;
selectInvert: string;
removeAll: string;
removeCurrent: string;
remove?: string;
selectAll?: string;
selectCurrent?: string;
selectInvert?: string;
removeAll?: string;
removeCurrent?: string;
}
export const transferProps = () => ({
@ -108,9 +108,8 @@ export const transferProps = () => ({
functionType<
(targetKeys: string[], direction: TransferDirection, moveKeys: string[]) => void
>(),
onSelectChange: functionType<
(sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void
>,
onSelectChange:
functionType<(sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void>(),
onSearch: functionType<(direction: TransferDirection, value: string) => void>(),
onScroll: functionType<(direction: TransferDirection, e: UIEvent) => void>(),
'onUpdate:targetKeys': functionType<(keys: string[]) => void>(),
@ -177,15 +176,16 @@ const Transfer = defineComponent({
const moveTo = (direction: TransferDirection) => {
const { targetKeys = [], dataSource = [] } = props;
const moveKeys = direction === 'right' ? sourceSelectedKeys.value : targetSelectedKeys.value;
const dataSourceDisabledKeysMap = groupDisabledKeysMap(dataSource);
// filter the disabled options
const newMoveKeys = moveKeys.filter(
key => !dataSource.some(data => !!(key === data.key && data.disabled)),
);
const newMoveKeys = moveKeys.filter(key => !dataSourceDisabledKeysMap.has(key));
const newMoveKeysMap = groupKeysMap(newMoveKeys);
// move items to target box
const newTargetKeys =
direction === 'right'
? newMoveKeys.concat(targetKeys)
: targetKeys.filter(targetKey => newMoveKeys.indexOf(targetKey) === -1);
: targetKeys.filter(targetKey => !newMoveKeysMap.has(targetKey));
// empty checked keys
const oppositeDirection = direction === 'right' ? 'left' : 'right';
@ -309,16 +309,16 @@ const Transfer = defineComponent({
const ld = [];
const rd = new Array(targetKeys.length);
const targetKeysMap = groupKeysMap(targetKeys);
dataSource.forEach(record => {
if (rowKey) {
record.key = rowKey(record);
}
// rightDataSource should be ordered by targetKeys
// leftDataSource should be ordered by dataSource
const indexOfKey = targetKeys.indexOf(record.key);
if (indexOfKey !== -1) {
rd[indexOfKey] = record;
// rightData should be ordered by targetKeys
// leftData should be ordered by dataSource
if (targetKeysMap.has(record.key)) {
rd[targetKeysMap.get(record.key)!] = record;
} else {
ld.push(record);
}

View File

@ -12,6 +12,7 @@ import { watchEffect, computed, defineComponent, ref } from 'vue';
import type { RadioChangeEvent } from '../radio/interface';
import type { TransferDirection, TransferItem } from './index';
import { stringType, arrayType, booleanType } from '../_util/type';
import { groupKeysMap } from '../_util/transKeys';
const defaultRender = () => null;
@ -125,9 +126,8 @@ export default defineComponent({
if (checkedKeys.length === 0) {
return 'none';
}
if (
filteredItems.value.every(item => checkedKeys.indexOf(item.key) >= 0 || !!item.disabled)
) {
const checkedKeysMap = groupKeysMap(checkedKeys);
if (filteredItems.value.every(item => checkedKeysMap.has(item.key) || !!item.disabled)) {
return 'all';
}
return 'part';
@ -147,7 +147,7 @@ export default defineComponent({
const checkedAll = checkStatus.value === 'all';
const checkAllCheckbox = (
<Checkbox
disabled={disabled}
disabled={props.dataSource?.length === 0 || disabled}
checked={checkedAll}
indeterminate={checkStatus.value === 'part'}
class={`${prefixCls}-checkbox`}
@ -181,7 +181,7 @@ export default defineComponent({
if (filterOption) {
return filterOption(filterValue.value, item);
}
return text.indexOf(filterValue.value) >= 0;
return text.includes(filterValue.value);
};
const getSelectAllLabel = (selectedCount: number, totalCount: number) => {
@ -199,6 +199,11 @@ export default defineComponent({
);
};
const notFoundContentEle = computed(() =>
Array.isArray(props.notFoundContent)
? props.notFoundContent[props.direction === 'left' ? 0 : 1]
: props.notFoundContent,
);
const getListBody = (
prefixCls: string,
searchPlaceholder: string,
@ -237,7 +242,7 @@ export default defineComponent({
bodyNode = filteredItems.value.length ? (
bodyContent
) : (
<div class={`${prefixCls}-body-not-found`}>{props.notFoundContent}</div>
<div class={`${prefixCls}-body-not-found`}>{notFoundContentEle.value}</div>
);
}