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(
|
||||
props.filteredRenderItems.length / mergedPagination.value.pageSize,
|
||||
);
|
||||
|
||||
if (current.value > maxPageCount) {
|
||||
current.value = maxPageCount;
|
||||
}
|
||||
current.value = Math.min(current.value, maxPageCount);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue