perf: transfer
parent
68d295d7ef
commit
4ccb1c3e19
|
@ -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;
|
||||||
|
};
|
|
@ -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 },
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue