Skip to content

Commit 3736496

Browse files
authored
fix(runtime-core): avoid unmount teleport's children multiple times (#3499)
fix #3497
1 parent 117a61b commit 3736496

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

packages/runtime-core/__tests__/components/Teleport.spec.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import {
88
ref,
99
nextTick,
1010
markRaw,
11-
defineComponent
11+
defineComponent,
12+
withDirectives,
13+
createApp
1214
} from '@vue/runtime-test'
1315
import { createVNode, Fragment } from '../../src/vnode'
1416
import { compile, render as domRender } from 'vue'
@@ -432,4 +434,42 @@ describe('renderer: teleport', () => {
432434
`"<div>teleported</div><span>false</span><!--v-if-->"`
433435
)
434436
})
437+
438+
// #3497
439+
test(`the dir hooks of the Teleport's children should be called correctly`, async () => {
440+
const target = nodeOps.createElement('div')
441+
const root = nodeOps.createElement('div')
442+
const toggle = ref(true)
443+
const dir = {
444+
mounted: jest.fn(),
445+
unmounted: jest.fn()
446+
}
447+
448+
const app = createApp({
449+
setup() {
450+
return () => {
451+
return toggle.value
452+
? h(Teleport, { to: target }, [
453+
withDirectives(h('div', ['foo']), [[dir]])
454+
])
455+
: null
456+
}
457+
}
458+
})
459+
app.mount(root)
460+
461+
expect(serializeInner(root)).toMatchInlineSnapshot(
462+
`"<!--teleport start--><!--teleport end-->"`
463+
)
464+
expect(serializeInner(target)).toMatchInlineSnapshot(`"<div>foo</div>"`)
465+
expect(dir.mounted).toHaveBeenCalledTimes(1)
466+
expect(dir.unmounted).toHaveBeenCalledTimes(0)
467+
468+
toggle.value = false
469+
await nextTick()
470+
expect(serializeInner(root)).toMatchInlineSnapshot(`"<!---->"`)
471+
expect(serializeInner(target)).toMatchInlineSnapshot(`""`)
472+
expect(dir.mounted).toHaveBeenCalledTimes(1)
473+
expect(dir.unmounted).toHaveBeenCalledTimes(1)
474+
})
435475
})

packages/runtime-core/src/renderer.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,7 +2096,16 @@ function baseCreateRenderer(
20962096
invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')
20972097
}
20982098

2099-
if (
2099+
if (shapeFlag & ShapeFlags.TELEPORT) {
2100+
;(vnode.type as typeof TeleportImpl).remove(
2101+
vnode,
2102+
parentComponent,
2103+
parentSuspense,
2104+
optimized,
2105+
internals,
2106+
doRemove
2107+
)
2108+
} else if (
21002109
dynamicChildren &&
21012110
// #1153: fast path should not be taken for non-stable (v-for) fragments
21022111
(type !== Fragment ||
@@ -2119,17 +2128,6 @@ function baseCreateRenderer(
21192128
unmountChildren(children as VNode[], parentComponent, parentSuspense)
21202129
}
21212130

2122-
if (shapeFlag & ShapeFlags.TELEPORT) {
2123-
;(vnode.type as typeof TeleportImpl).remove(
2124-
vnode,
2125-
parentComponent,
2126-
parentSuspense,
2127-
optimized,
2128-
internals,
2129-
doRemove
2130-
)
2131-
}
2132-
21332131
if (doRemove) {
21342132
remove(vnode)
21352133
}

0 commit comments

Comments
 (0)