mirror of https://github.com/vuejs/core.git
fix(suspense): handle edge case in patching list nodes within Suspense (#13306)
close #13305
This commit is contained in:
parent
cf5a5e0edf
commit
772b0087cb
|
@ -861,6 +861,114 @@ describe('renderer: optimized mode', () => {
|
|||
expect(inner(root)).toBe('<div><div>true</div></div>')
|
||||
})
|
||||
|
||||
// #13305
|
||||
test('patch Suspense nested in list nodes in optimized mode', async () => {
|
||||
const deps: Promise<any>[] = []
|
||||
|
||||
const Item = {
|
||||
props: {
|
||||
someId: { type: Number, required: true },
|
||||
},
|
||||
async setup(props: any) {
|
||||
const p = new Promise(resolve => setTimeout(resolve, 1))
|
||||
deps.push(p)
|
||||
|
||||
await p
|
||||
return () => (
|
||||
openBlock(),
|
||||
createElementBlock('li', null, [
|
||||
createElementVNode(
|
||||
'p',
|
||||
null,
|
||||
String(props.someId),
|
||||
PatchFlags.TEXT,
|
||||
),
|
||||
])
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
const list = ref([1, 2, 3])
|
||||
const App = {
|
||||
setup() {
|
||||
return () => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
[
|
||||
createElementVNode(
|
||||
'p',
|
||||
null,
|
||||
JSON.stringify(list.value),
|
||||
PatchFlags.TEXT,
|
||||
),
|
||||
createElementVNode('ol', null, [
|
||||
(openBlock(),
|
||||
createBlock(SuspenseImpl, null, {
|
||||
fallback: withCtx(() => [
|
||||
createElementVNode('li', null, 'Loading…'),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
(openBlock(true),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(list.value, id => {
|
||||
return (
|
||||
openBlock(),
|
||||
createBlock(
|
||||
Item,
|
||||
{
|
||||
key: id,
|
||||
'some-id': id,
|
||||
},
|
||||
null,
|
||||
PatchFlags.PROPS,
|
||||
['some-id'],
|
||||
)
|
||||
)
|
||||
}),
|
||||
PatchFlags.KEYED_FRAGMENT,
|
||||
)),
|
||||
]),
|
||||
_: 1 /* STABLE */,
|
||||
})),
|
||||
]),
|
||||
],
|
||||
PatchFlags.STABLE_FRAGMENT,
|
||||
)
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
const app = createApp(App)
|
||||
app.mount(root)
|
||||
expect(inner(root)).toBe(`<p>[1,2,3]</p>` + `<ol><li>Loading…</li></ol>`)
|
||||
|
||||
await Promise.all(deps)
|
||||
await nextTick()
|
||||
expect(inner(root)).toBe(
|
||||
`<p>[1,2,3]</p>` +
|
||||
`<ol>` +
|
||||
`<li><p>1</p></li>` +
|
||||
`<li><p>2</p></li>` +
|
||||
`<li><p>3</p></li>` +
|
||||
`</ol>`,
|
||||
)
|
||||
|
||||
list.value = [3, 1, 2]
|
||||
await nextTick()
|
||||
expect(inner(root)).toBe(
|
||||
`<p>[3,1,2]</p>` +
|
||||
`<ol>` +
|
||||
`<li><p>3</p></li>` +
|
||||
`<li><p>1</p></li>` +
|
||||
`<li><p>2</p></li>` +
|
||||
`</ol>`,
|
||||
)
|
||||
})
|
||||
|
||||
// #4183
|
||||
test('should not take unmount children fast path /w Suspense', async () => {
|
||||
const show = ref(true)
|
||||
|
|
|
@ -961,7 +961,8 @@ function baseCreateRenderer(
|
|||
// which also requires the correct parent container
|
||||
!isSameVNodeType(oldVNode, newVNode) ||
|
||||
// - In the case of a component, it could contain anything.
|
||||
oldVNode.shapeFlag & (ShapeFlags.COMPONENT | ShapeFlags.TELEPORT))
|
||||
oldVNode.shapeFlag &
|
||||
(ShapeFlags.COMPONENT | ShapeFlags.TELEPORT | ShapeFlags.SUSPENSE))
|
||||
? hostParentNode(oldVNode.el)!
|
||||
: // In other cases, the parent container is not actually used so we
|
||||
// just pass the block element here to avoid a DOM parentNode call.
|
||||
|
|
Loading…
Reference in New Issue