fix(teleport): targetAnchor should also be removed when unmounted (#2870)

* fix(teleport): targetAnchor should also be removed when unmounted

* fix(teleport): targetAnchor should also be removed when unmounted
This commit is contained in:
2021-03-23 17:19:09 +08:00 committed by GitHub
parent 3b3a9a1f52
commit 21d1288133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 29 deletions

View File

@ -128,19 +128,23 @@ describe('renderer: teleport', () => {
const target = nodeOps.createElement('div') const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div') const root = nodeOps.createElement('div')
render( function testUnmount(props: any) {
h(() => [ render(
h(Teleport, { to: target }, h('div', 'teleported')), h(() => [h(Teleport, props, h('div', 'teleported')), h('div', 'root')]),
h('div', 'root') root
]), )
root expect(serializeInner(target)).toMatchInlineSnapshot(
) props.disabled ? `""` : `"<div>teleported</div>"`
expect(serializeInner(target)).toMatchInlineSnapshot( )
`"<div>teleported</div>"`
)
render(null, root) render(null, root)
expect(serializeInner(target)).toBe('') expect(serializeInner(target)).toBe('')
expect(target.children.length).toBe(0)
}
testUnmount({ to: target, disabled: false })
testUnmount({ to: target, disabled: true })
testUnmount({ to: null, disabled: true })
}) })
test('multiple teleport with same target', () => { test('multiple teleport with same target', () => {

View File

@ -218,13 +218,22 @@ export const TeleportImpl = {
remove( remove(
vnode: VNode, vnode: VNode,
{ r: remove, o: { remove: hostRemove } }: RendererInternals { r: remove, o: { remove: hostRemove } }: RendererInternals,
doRemove: Boolean
) { ) {
const { shapeFlag, children, anchor } = vnode const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
hostRemove(anchor!)
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { if (target) {
for (let i = 0; i < (children as VNode[]).length; i++) { hostRemove(targetAnchor!)
remove((children as VNode[])[i]) }
// an unmounted teleport should always remove its children if not disabled
if (doRemove || !isTeleportDisabled(props)) {
hostRemove(anchor!)
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
for (let i = 0; i < (children as VNode[]).length; i++) {
remove((children as VNode[])[i])
}
} }
} }
}, },

View File

@ -57,11 +57,7 @@ import {
queueEffectWithSuspense, queueEffectWithSuspense,
SuspenseImpl SuspenseImpl
} from './components/Suspense' } from './components/Suspense'
import { import { TeleportImpl, TeleportVNode } from './components/Teleport'
isTeleportDisabled,
TeleportImpl,
TeleportVNode
} from './components/Teleport'
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive' import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr' import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
import { import {
@ -2111,12 +2107,8 @@ function baseCreateRenderer(
unmountChildren(children as VNode[], parentComponent, parentSuspense) unmountChildren(children as VNode[], parentComponent, parentSuspense)
} }
// an unmounted teleport should always remove its children if not disabled if (shapeFlag & ShapeFlags.TELEPORT) {
if ( ;(vnode.type as typeof TeleportImpl).remove(vnode, internals, doRemove)
shapeFlag & ShapeFlags.TELEPORT &&
(doRemove || !isTeleportDisabled(vnode.props))
) {
;(vnode.type as typeof TeleportImpl).remove(vnode, internals)
} }
if (doRemove) { if (doRemove) {