fix(teleport): ensure descendent component would be unmounted correctly (#6529)

fix #6347
This commit is contained in:
pupu 2023-10-20 16:42:04 +08:00 committed by GitHub
parent 8f0472c9ab
commit 4162311efd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 15 deletions

View File

@ -172,6 +172,31 @@ describe('renderer: teleport', () => {
expect(serializeInner(target)).toBe('') expect(serializeInner(target)).toBe('')
}) })
// #6347
test('descendent component should be unmounted when teleport is disabled and unmounted', () => {
const root = nodeOps.createElement('div')
const CompWithHook = {
render() {
return [h('p'), h('p')]
},
beforeUnmount: vi.fn(),
unmounted: vi.fn()
}
render(
h(() => [h(Teleport, { to: null, disabled: true }, h(CompWithHook))]),
root
)
expect(CompWithHook.beforeUnmount).toBeCalledTimes(0)
expect(CompWithHook.unmounted).toBeCalledTimes(0)
render(null, root)
expect(CompWithHook.beforeUnmount).toBeCalledTimes(1)
expect(CompWithHook.unmounted).toBeCalledTimes(1)
})
test('multiple teleport with same target', () => { test('multiple teleport with same target', () => {
const target = nodeOps.createElement('div') const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div') const root = nodeOps.createElement('div')

View File

@ -239,7 +239,7 @@ export const TeleportImpl = {
parentSuspense: SuspenseBoundary | null, parentSuspense: SuspenseBoundary | null,
optimized: boolean, optimized: boolean,
{ um: unmount, o: { remove: hostRemove } }: RendererInternals, { um: unmount, o: { remove: hostRemove } }: RendererInternals,
doRemove: Boolean doRemove: boolean
) { ) {
const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
@ -247,20 +247,19 @@ export const TeleportImpl = {
hostRemove(targetAnchor!) hostRemove(targetAnchor!)
} }
// an unmounted teleport should always remove its children if not disabled // an unmounted teleport should always unmount its children whether it's disabled or not
if (doRemove || !isTeleportDisabled(props)) { doRemove && hostRemove(anchor!)
hostRemove(anchor!) if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { const shouldRemove = doRemove || !isTeleportDisabled(props)
for (let i = 0; i < (children as VNode[]).length; i++) { for (let i = 0; i < (children as VNode[]).length; i++) {
const child = (children as VNode[])[i] const child = (children as VNode[])[i]
unmount( unmount(
child, child,
parentComponent, parentComponent,
parentSuspense, parentSuspense,
true, shouldRemove,
!!child.dynamicChildren !!child.dynamicChildren
) )
}
} }
} }
}, },