From ccdc634c2498f56f5f4492fc53ded591896d6498 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Wed, 7 Feb 2024 22:01:22 +0800 Subject: [PATCH] fix(runtime-vapor): v-for move list items are not always effective (#121) --- packages/runtime-vapor/__tests__/for.spec.ts | 62 ++++++++++++++++++++ packages/runtime-vapor/src/for.ts | 4 +- 2 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 packages/runtime-vapor/__tests__/for.spec.ts diff --git a/packages/runtime-vapor/__tests__/for.spec.ts b/packages/runtime-vapor/__tests__/for.spec.ts new file mode 100644 index 000000000..c0dbf7b06 --- /dev/null +++ b/packages/runtime-vapor/__tests__/for.spec.ts @@ -0,0 +1,62 @@ +import { + computed, + createFor, + createTextNode, + nextTick, + ref, + renderEffect, + setText, +} from '../src' +import { makeRender } from './_utils' + +const define = makeRender() + +describe('createFor', () => { + test('basic', async () => { + const list = ref([{ name: '1' }, { name: '2' }, { name: '3' }]) + const sort = ref(false) + const sortedList = computed(() => + sort.value ? Array.from(list.value).reverse() : list.value, + ) + + const { host } = define(() => { + const n1 = createFor( + () => sortedList.value, + block => { + const n3 = createTextNode() + renderEffect(() => { + const [item] = block.s + setText(n3, item.name) + }) + return [n3] + }, + ) + return [n1] + }).render() + + expect(host.innerHTML).toBe('123') + + // add + list.value.push({ name: '4' }) + await nextTick() + expect(host.innerHTML).toBe('1234') + + // move + sort.value = true + await nextTick() + expect(host.innerHTML).toBe('4321') + sort.value = false + await nextTick() + expect(host.innerHTML).toBe('1234') + + // change + list.value[0].name = 'a' + await nextTick() + expect(host.innerHTML).toBe('a234') + + // remove + list.value = [] + await nextTick() + expect(host.innerHTML).toBe('') + }) +}) diff --git a/packages/runtime-vapor/src/for.ts b/packages/runtime-vapor/src/for.ts index 4eb005ee5..4e2f022fa 100644 --- a/packages/runtime-vapor/src/for.ts +++ b/packages/runtime-vapor/src/for.ts @@ -6,7 +6,6 @@ import { type Block, type Fragment, fragmentKey } from './render' interface ForBlock extends Fragment { scope: EffectScope - item: any s: [any, number] // state, use short key since it's used a lot in generated code update: () => void key: any @@ -41,7 +40,6 @@ export const createFor = ( nodes: null as any, update: null as any, scope, - item, s: [item, index], key: getKey && getKey(item, index), memo: getMemo && getMemo(item), @@ -99,7 +97,7 @@ export const createFor = ( newIndex = oldIndex, ) => { if ( - newItem !== block.item || + newItem !== block.s[0] || newIndex !== oldIndex || !isReactive(newItem) ) {