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( const maxPageCount = Math.ceil(
props.filteredRenderItems.length / mergedPagination.value.pageSize, props.filteredRenderItems.length / mergedPagination.value.pageSize,
); );
current.value = Math.min(current.value, maxPageCount);
if (current.value > maxPageCount) {
current.value = maxPageCount;
}
} }
}, },
{ immediate: true }, { immediate: true },

View File

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

View File

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