diff --git a/packages/core/src/__tests__/array.spec.ts b/packages/core/src/__tests__/array.spec.ts index cdb92ccc750..d41ac5d7e80 100644 --- a/packages/core/src/__tests__/array.spec.ts +++ b/packages/core/src/__tests__/array.spec.ts @@ -297,23 +297,24 @@ test('fault tolerance', () => { array.move(0, 1) expect(array.value).toEqual([1]) array.moveUp(1) - expect(array.value).toEqual([undefined, 1]) + expect(array.value).toEqual([1]) array.moveDown(1) - expect(array.value).toEqual([1, undefined]) + expect(array.value).toEqual([1]) array.insert(1) - expect(array.value).toEqual([1, undefined]) + expect(array.value).toEqual([1]) array2.move(1, 1) expect(array2.value).toEqual([1, 2]) + array2.push(3) array2.moveUp(2) - expect(array2.value).toEqual([1, undefined, 2]) + expect(array2.value).toEqual([1, 3, 2]) array2.moveUp(0) - expect(array2.value).toEqual([undefined, 2, 1]) + expect(array2.value).toEqual([3, 2, 1]) array2.moveDown(0) - expect(array2.value).toEqual([2, undefined, 1]) + expect(array2.value).toEqual([2, 3, 1]) array2.moveDown(1) - expect(array2.value).toEqual([2, 1, undefined]) + expect(array2.value).toEqual([2, 1, 3]) array2.moveDown(2) - expect(array2.value).toEqual([undefined, 2, 1]) + expect(array2.value).toEqual([3, 2, 1]) }) test('mutation fault tolerance', () => { diff --git a/packages/core/src/models/ArrayField.ts b/packages/core/src/models/ArrayField.ts index f9607729689..6e38d1a9273 100644 --- a/packages/core/src/models/ArrayField.ts +++ b/packages/core/src/models/ArrayField.ts @@ -1,4 +1,4 @@ -import { isArr } from '@formily/shared' +import { isArr, move } from '@formily/shared' import { action, reaction } from '@formily/reactive' import { spliceArrayState, @@ -68,6 +68,9 @@ export class ArrayField< if (!isArr(this.value)) { this.value = [] } + if (items.length === 0) { + return + } spliceArrayState(this, { startIndex: index, insertCount: items.length, @@ -115,9 +118,7 @@ export class ArrayField< if (!isArr(this.value)) return if (fromIndex === toIndex) return return action(() => { - const fromItem = this.value[fromIndex] - this.value.splice(fromIndex, 1) - this.value.splice(toIndex, 0, fromItem) + move(this.value, fromIndex, toIndex) exchangeArrayState(this, { fromIndex, toIndex, diff --git a/packages/shared/src/__tests__/index.spec.ts b/packages/shared/src/__tests__/index.spec.ts index 837f58b00f9..66b490a610b 100644 --- a/packages/shared/src/__tests__/index.spec.ts +++ b/packages/shared/src/__tests__/index.spec.ts @@ -4,6 +4,7 @@ import { isEqual } from '../compare' import { toArr, every, + move, some, findIndex, find, @@ -958,3 +959,25 @@ test('applyMiddleware with error', async () => { expect(e).toEqual('this is error') } }) + +test('move', () => { + const array1 = [1] + move(array1, 1, 0) + expect(array1).toEqual([1]) + move(array1, 0, 1) + expect(array1).toEqual([1]) + move(array1, -1, 1) + expect(array1).toEqual([1]) + move(array1, 0, 3) + expect(array1).toEqual([1]) + + const array2 = [0, 1, 2] + move(array2, 0, 2) + expect(array2).toEqual([1, 2, 0]) + move(array2, 1, 1) + expect(array2).toEqual([1, 2, 0]) + + const array3 = [0, 1, 2, 3] + move(array3, 3, 1) + expect(array3).toEqual([0, 3, 1, 2]) +}) diff --git a/packages/shared/src/array.ts b/packages/shared/src/array.ts index 0d2b9b1d50f..efbf3772e26 100644 --- a/packages/shared/src/array.ts +++ b/packages/shared/src/array.ts @@ -279,3 +279,35 @@ export function includes(val: any, searchElement: any, revert?: boolean) { if (isStr(val)) return val.includes(searchElement) return some(val, (item) => item === searchElement, revert) } + +export function move( + array: T[], + fromIndex: number, + toIndex: number +) { + if (fromIndex === toIndex) return array + + if ( + toIndex < 0 || + fromIndex < 0 || + toIndex > array.length - 1 || + fromIndex > array.length - 1 + ) { + return array + } + + if (fromIndex < toIndex) { + const fromItem = array[fromIndex] + for (let index = fromIndex; index < toIndex; index++) { + array[index] = array[index + 1] + } + array[toIndex] = fromItem + } else { + const fromItem = array[fromIndex] + for (let index = fromIndex; index > toIndex; index--) { + array[index] = array[index - 1] + } + array[toIndex] = fromItem + } + return array +}