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 root = nodeOps.createElement('div')
render(
h(() => [
h(Teleport, { to: target }, h('div', 'teleported')),
h('div', 'root')
]),
root
)
expect(serializeInner(target)).toMatchInlineSnapshot(
`"<div>teleported</div>"`
)
function testUnmount(props: any) {
render(
h(() => [h(Teleport, props, h('div', 'teleported')), h('div', 'root')]),
root
)
expect(serializeInner(target)).toMatchInlineSnapshot(
props.disabled ? `""` : `"<div>teleported</div>"`
)
render(null, root)
expect(serializeInner(target)).toBe('')
render(null, root)
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', () => {

View File

@ -218,13 +218,22 @@ export const TeleportImpl = {
remove(
vnode: VNode,
{ r: remove, o: { remove: hostRemove } }: RendererInternals
{ r: remove, o: { remove: hostRemove } }: RendererInternals,
doRemove: Boolean
) {
const { shapeFlag, children, anchor } = vnode
hostRemove(anchor!)
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
for (let i = 0; i < (children as VNode[]).length; i++) {
remove((children as VNode[])[i])
const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
if (target) {
hostRemove(targetAnchor!)
}
// 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,
SuspenseImpl
} from './components/Suspense'
import {
isTeleportDisabled,
TeleportImpl,
TeleportVNode
} from './components/Teleport'
import { TeleportImpl, TeleportVNode } from './components/Teleport'
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
import {
@ -2111,12 +2107,8 @@ function baseCreateRenderer(
unmountChildren(children as VNode[], parentComponent, parentSuspense)
}
// an unmounted teleport should always remove its children if not disabled
if (
shapeFlag & ShapeFlags.TELEPORT &&
(doRemove || !isTeleportDisabled(vnode.props))
) {
;(vnode.type as typeof TeleportImpl).remove(vnode, internals)
if (shapeFlag & ShapeFlags.TELEPORT) {
;(vnode.type as typeof TeleportImpl).remove(vnode, internals, doRemove)
}
if (doRemove) {