fix(Teleport): component with multi roots should be removed when unmounted (#3157)

fix #3156
This commit is contained in:
HcySunYang 2021-03-25 23:02:50 +08:00 committed by GitHub
parent 0a583d5ca2
commit 776951315d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 4 deletions

View File

@ -147,6 +147,26 @@ describe('renderer: teleport', () => {
testUnmount({ to: null, disabled: true }) testUnmount({ to: null, disabled: true })
}) })
test('component with multi roots should be removed when unmounted', () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
const Comp = {
render() {
return [h('p'), h('p')]
}
}
render(
h(() => [h(Teleport, { to: target }, h(Comp)), h('div', 'root')]),
root
)
expect(serializeInner(target)).toMatchInlineSnapshot(`"<p></p><p></p>"`)
render(null, root)
expect(serializeInner(target)).toBe('')
})
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

@ -21,7 +21,7 @@ export interface TeleportProps {
export const isTeleport = (type: any): boolean => type.__isTeleport export const isTeleport = (type: any): boolean => type.__isTeleport
export const isTeleportDisabled = (props: VNode['props']): boolean => const isTeleportDisabled = (props: VNode['props']): boolean =>
props && (props.disabled || props.disabled === '') props && (props.disabled || props.disabled === '')
const isTargetSVG = (target: RendererElement): boolean => const isTargetSVG = (target: RendererElement): boolean =>
@ -218,7 +218,10 @@ export const TeleportImpl = {
remove( remove(
vnode: VNode, vnode: VNode,
{ r: remove, o: { remove: hostRemove } }: RendererInternals, parentComponent: ComponentInternalInstance | null,
parentSuspense: SuspenseBoundary | null,
optimized: boolean,
{ 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
@ -232,7 +235,13 @@ export const TeleportImpl = {
hostRemove(anchor!) hostRemove(anchor!)
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
for (let i = 0; i < (children as VNode[]).length; i++) { for (let i = 0; i < (children as VNode[]).length; i++) {
remove((children as VNode[])[i]) unmount(
(children as VNode[])[i],
parentComponent,
parentSuspense,
true,
optimized
)
} }
} }
} }

View File

@ -2108,7 +2108,14 @@ function baseCreateRenderer(
} }
if (shapeFlag & ShapeFlags.TELEPORT) { if (shapeFlag & ShapeFlags.TELEPORT) {
;(vnode.type as typeof TeleportImpl).remove(vnode, internals, doRemove) ;(vnode.type as typeof TeleportImpl).remove(
vnode,
parentComponent,
parentSuspense,
optimized,
internals,
doRemove
)
} }
if (doRemove) { if (doRemove) {