Skip to content

Commit

Permalink
fix(teleport): targetAnchor should also be removed when unmounted (#2870
Browse files Browse the repository at this point in the history
)

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

* fix(teleport): targetAnchor should also be removed when unmounted
  • Loading branch information
leaon4 authored Mar 23, 2021
1 parent 3b3a9a1 commit 21d1288
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 29 deletions.
28 changes: 16 additions & 12 deletions packages/runtime-core/__tests__/components/Teleport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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('')
expect(target.children.length).toBe(0)
}

render(null, root)
expect(serializeInner(target)).toBe('')
testUnmount({ to: target, disabled: false })
testUnmount({ to: target, disabled: true })
testUnmount({ to: null, disabled: true })
})

test('multiple teleport with same target', () => {
Expand Down
21 changes: 15 additions & 6 deletions packages/runtime-core/src/components/Teleport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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])
}
}
}
},
Expand Down
14 changes: 3 additions & 11 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 21d1288

Please sign in to comment.