Skip to content

Commit 348ffaf

Browse files
authored
fix(runtime-vapor): resolve multiple vFor rendering issues (#13714)
1 parent f70f9d1 commit 348ffaf

File tree

2 files changed

+52
-60
lines changed

2 files changed

+52
-60
lines changed

packages/runtime-vapor/__tests__/for.spec.ts

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ describe('createFor', () => {
778778
)
779779
})
780780

781-
test.todo('prepend', async () => {
781+
test('prepend', async () => {
782782
const arr = ref<number[]>([4, 5])
783783
const { host, html } = render(arr)
784784
expect(host.children.length).toBe(2)
@@ -940,7 +940,7 @@ describe('createFor', () => {
940940
)
941941
})
942942

943-
test.todo('remove from beginning and insert at end', async () => {
943+
test('remove from beginning and insert at end', async () => {
944944
const arr = ref<number[]>([1, 2, 3])
945945
const { host, html } = render(arr)
946946
expect(host.children.length).toBe(3)
@@ -1028,7 +1028,7 @@ describe('createFor', () => {
10281028
)
10291029
})
10301030

1031-
test.todo('move to left & replace', async () => {
1031+
test('move to left & replace', async () => {
10321032
const arr = ref<number[]>([1, 2, 3, 4, 5])
10331033
const { host, html } = render(arr)
10341034
expect(host.children.length).toBe(5)
@@ -1044,7 +1044,7 @@ describe('createFor', () => {
10441044
)
10451045
})
10461046

1047-
test.todo('move to left and leaves hold', async () => {
1047+
test('move to left and leaves hold', async () => {
10481048
const arr = ref<number[]>([1, 4, 5])
10491049
const { host, html } = render(arr)
10501050
expect(host.children.length).toBe(3)
@@ -1058,24 +1058,21 @@ describe('createFor', () => {
10581058
expect(html()).toBe(`<span>4</span><span>6</span><!--for-->`)
10591059
})
10601060

1061-
test.todo(
1062-
'moved and set to undefined element ending at the end',
1063-
async () => {
1064-
const arr = ref<number[]>([2, 4, 5])
1065-
const { host, html } = render(arr)
1066-
expect(host.children.length).toBe(3)
1067-
expect(html()).toBe(
1068-
`<span>2</span><span>4</span><span>5</span><!--for-->`,
1069-
)
1061+
test('moved and set to undefined element ending at the end', async () => {
1062+
const arr = ref<number[]>([2, 4, 5])
1063+
const { host, html } = render(arr)
1064+
expect(host.children.length).toBe(3)
1065+
expect(html()).toBe(
1066+
`<span>2</span><span>4</span><span>5</span><!--for-->`,
1067+
)
10701068

1071-
arr.value = [4, 5, 3]
1072-
await nextTick()
1073-
expect(host.children.length).toBe(3)
1074-
expect(html()).toBe(
1075-
`<span>4</span><span>5</span><span>3</span><!--for-->`,
1076-
)
1077-
},
1078-
)
1069+
arr.value = [4, 5, 3]
1070+
await nextTick()
1071+
expect(host.children.length).toBe(3)
1072+
expect(html()).toBe(
1073+
`<span>4</span><span>5</span><span>3</span><!--for-->`,
1074+
)
1075+
})
10791076

10801077
test('reverse element', async () => {
10811078
const arr = ref<number[]>([1, 2, 3, 4, 5, 6, 7, 8])
@@ -1323,7 +1320,7 @@ describe('createFor', () => {
13231320
}).render()
13241321
}
13251322

1326-
test.todo('move a key in non-keyed nodes with a size up', async () => {
1323+
test('move a key in non-keyed nodes with a size up', async () => {
13271324
const arr = ref<any[]>([1, 'a', 'b', 'c'])
13281325
const { host, html } = define({
13291326
setup() {

packages/runtime-vapor/src/apiCreateFor.ts

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,15 @@ export const createFor = (
196196
endOffset++
197197
continue
198198
}
199-
if (endOffset !== 0) {
200-
anchorFallback = normalizeAnchor(newBlocks[currentIndex + 1].nodes)
201-
}
202199
break
203200
}
204201

202+
if (endOffset !== 0) {
203+
anchorFallback = normalizeAnchor(
204+
newBlocks[newLength - endOffset].nodes,
205+
)
206+
}
207+
205208
while (startOffset < sharedBlockCount - endOffset) {
206209
const currentItem = getItem(source, startOffset)
207210
const currentKey = getKey(...currentItem)
@@ -251,12 +254,7 @@ export const createFor = (
251254
previousKeyIndexPairs.length = previousKeyIndexInsertIndex
252255

253256
const previousKeyIndexMap = new Map(previousKeyIndexPairs)
254-
const blocksToMount: [
255-
blockIndex: number,
256-
blockItem: ReturnType<typeof getItem>,
257-
blockKey: any,
258-
anchorOffset: number,
259-
][] = []
257+
const operations: (() => void)[] = []
260258

261259
const relocateOrMountBlock = (
262260
blockIndex: number,
@@ -269,21 +267,30 @@ export const createFor = (
269267
const reusedBlock = (newBlocks[blockIndex] =
270268
oldBlocks[previousIndex])
271269
update(reusedBlock, ...blockItem)
272-
insert(
273-
reusedBlock,
274-
parent!,
275-
anchorOffset === -1
276-
? anchorFallback
277-
: normalizeAnchor(newBlocks[anchorOffset].nodes),
278-
)
279270
previousKeyIndexMap.delete(blockKey)
271+
if (previousIndex !== blockIndex) {
272+
operations.push(() =>
273+
insert(
274+
reusedBlock,
275+
parent!,
276+
anchorOffset === -1
277+
? anchorFallback
278+
: normalizeAnchor(newBlocks[anchorOffset].nodes),
279+
),
280+
)
281+
}
280282
} else {
281-
blocksToMount.push([
282-
blockIndex,
283-
blockItem,
284-
blockKey,
285-
anchorOffset,
286-
])
283+
operations.push(() =>
284+
mount(
285+
source,
286+
blockIndex,
287+
anchorOffset === -1
288+
? anchorFallback
289+
: normalizeAnchor(newBlocks[anchorOffset].nodes),
290+
blockItem,
291+
blockKey,
292+
),
293+
)
287294
}
288295
}
289296

@@ -303,7 +310,7 @@ export const createFor = (
303310
relocateOrMountBlock(i, blockItem, blockKey, -1)
304311
}
305312

306-
const useFastRemove = blocksToMount.length === newLength
313+
const useFastRemove = operations.length === newLength
307314

308315
for (const leftoverIndex of previousKeyIndexMap.values()) {
309316
unmount(
@@ -322,21 +329,9 @@ export const createFor = (
322329
}
323330
}
324331

325-
for (const [
326-
blockIndex,
327-
blockItem,
328-
blockKey,
329-
anchorOffset,
330-
] of blocksToMount) {
331-
mount(
332-
source,
333-
blockIndex,
334-
anchorOffset === -1
335-
? anchorFallback
336-
: normalizeAnchor(newBlocks[anchorOffset].nodes),
337-
blockItem,
338-
blockKey,
339-
)
332+
// perform mount and move operations
333+
for (const action of operations) {
334+
action()
340335
}
341336
}
342337
}

0 commit comments

Comments
 (0)