mirror of https://github.com/vuejs/core.git
fix(runtime-core): ensure correct anchor el for unresolved async components (#13560)
close #13559
This commit is contained in:
parent
9b029239ed
commit
7f2994393d
|
@ -2230,5 +2230,57 @@ describe('Suspense', () => {
|
||||||
fallback: [h('div'), h('div')],
|
fallback: [h('div'), h('div')],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #13559
|
||||||
|
test('renders multiple async components in Suspense with v-for and updates on items change', async () => {
|
||||||
|
const CompAsyncSetup = defineAsyncComponent({
|
||||||
|
props: ['item'],
|
||||||
|
render(ctx: any) {
|
||||||
|
return h('div', ctx.item.name)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const items = ref([
|
||||||
|
{ id: 1, name: '111' },
|
||||||
|
{ id: 2, name: '222' },
|
||||||
|
{ id: 3, name: '333' },
|
||||||
|
])
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
return () =>
|
||||||
|
h(Suspense, null, {
|
||||||
|
default: () =>
|
||||||
|
h(
|
||||||
|
Fragment,
|
||||||
|
null,
|
||||||
|
items.value.map(item =>
|
||||||
|
h(CompAsyncSetup, { item, key: item.id }),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(h(Comp), root)
|
||||||
|
await nextTick()
|
||||||
|
await Promise.all(deps)
|
||||||
|
|
||||||
|
expect(serializeInner(root)).toBe(
|
||||||
|
`<div>111</div><div>222</div><div>333</div>`,
|
||||||
|
)
|
||||||
|
|
||||||
|
items.value = [
|
||||||
|
{ id: 4, name: '444' },
|
||||||
|
{ id: 5, name: '555' },
|
||||||
|
{ id: 6, name: '666' },
|
||||||
|
]
|
||||||
|
await nextTick()
|
||||||
|
await Promise.all(deps)
|
||||||
|
expect(serializeInner(root)).toBe(
|
||||||
|
`<div>444</div><div>555</div><div>666</div>`,
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1226,6 +1226,7 @@ function baseCreateRenderer(
|
||||||
if (!initialVNode.el) {
|
if (!initialVNode.el) {
|
||||||
const placeholder = (instance.subTree = createVNode(Comment))
|
const placeholder = (instance.subTree = createVNode(Comment))
|
||||||
processCommentNode(null, placeholder, container!, anchor)
|
processCommentNode(null, placeholder, container!, anchor)
|
||||||
|
initialVNode.placeholder = placeholder.el
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setupRenderEffect(
|
setupRenderEffect(
|
||||||
|
@ -1979,8 +1980,12 @@ function baseCreateRenderer(
|
||||||
for (i = toBePatched - 1; i >= 0; i--) {
|
for (i = toBePatched - 1; i >= 0; i--) {
|
||||||
const nextIndex = s2 + i
|
const nextIndex = s2 + i
|
||||||
const nextChild = c2[nextIndex] as VNode
|
const nextChild = c2[nextIndex] as VNode
|
||||||
|
const anchorVNode = c2[nextIndex + 1] as VNode
|
||||||
const anchor =
|
const anchor =
|
||||||
nextIndex + 1 < l2 ? (c2[nextIndex + 1] as VNode).el : parentAnchor
|
nextIndex + 1 < l2
|
||||||
|
? // #13559, fallback to el placeholder for unresolved async component
|
||||||
|
anchorVNode.el || anchorVNode.placeholder
|
||||||
|
: parentAnchor
|
||||||
if (newIndexToOldIndexMap[i] === 0) {
|
if (newIndexToOldIndexMap[i] === 0) {
|
||||||
// mount new
|
// mount new
|
||||||
patch(
|
patch(
|
||||||
|
|
|
@ -196,6 +196,7 @@ export interface VNode<
|
||||||
|
|
||||||
// DOM
|
// DOM
|
||||||
el: HostNode | null
|
el: HostNode | null
|
||||||
|
placeholder: HostNode | null // async component el placeholder
|
||||||
anchor: HostNode | null // fragment anchor
|
anchor: HostNode | null // fragment anchor
|
||||||
target: HostElement | null // teleport target
|
target: HostElement | null // teleport target
|
||||||
targetStart: HostNode | null // teleport target start anchor
|
targetStart: HostNode | null // teleport target start anchor
|
||||||
|
@ -711,6 +712,8 @@ export function cloneVNode<T, U>(
|
||||||
suspense: vnode.suspense,
|
suspense: vnode.suspense,
|
||||||
ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),
|
ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),
|
||||||
ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),
|
ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),
|
||||||
|
placeholder: vnode.placeholder,
|
||||||
|
|
||||||
el: vnode.el,
|
el: vnode.el,
|
||||||
anchor: vnode.anchor,
|
anchor: vnode.anchor,
|
||||||
ctx: vnode.ctx,
|
ctx: vnode.ctx,
|
||||||
|
|
Loading…
Reference in New Issue