From 3736496006485e61614bef285ea89ea2a33134c4 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Tue, 30 Mar 2021 03:15:08 +0800 Subject: [PATCH] fix(runtime-core): avoid unmount teleport's children multiple times (#3499) fix #3497 --- .../__tests__/components/Teleport.spec.ts | 42 ++++++++++++++++++- packages/runtime-core/src/renderer.ts | 22 +++++----- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index f6babd926..8b234e2b1 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -8,7 +8,9 @@ import { ref, nextTick, markRaw, - defineComponent + defineComponent, + withDirectives, + createApp } from '@vue/runtime-test' import { createVNode, Fragment } from '../../src/vnode' import { compile, render as domRender } from 'vue' @@ -432,4 +434,42 @@ describe('renderer: teleport', () => { `"
teleported
false"` ) }) + + // #3497 + test(`the dir hooks of the Teleport's children should be called correctly`, async () => { + const target = nodeOps.createElement('div') + const root = nodeOps.createElement('div') + const toggle = ref(true) + const dir = { + mounted: jest.fn(), + unmounted: jest.fn() + } + + const app = createApp({ + setup() { + return () => { + return toggle.value + ? h(Teleport, { to: target }, [ + withDirectives(h('div', ['foo']), [[dir]]) + ]) + : null + } + } + }) + app.mount(root) + + expect(serializeInner(root)).toMatchInlineSnapshot( + `""` + ) + expect(serializeInner(target)).toMatchInlineSnapshot(`"
foo
"`) + expect(dir.mounted).toHaveBeenCalledTimes(1) + expect(dir.unmounted).toHaveBeenCalledTimes(0) + + toggle.value = false + await nextTick() + expect(serializeInner(root)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target)).toMatchInlineSnapshot(`""`) + expect(dir.mounted).toHaveBeenCalledTimes(1) + expect(dir.unmounted).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 4375dcdbf..5122e7a91 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -2096,7 +2096,16 @@ function baseCreateRenderer( invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount') } - if ( + if (shapeFlag & ShapeFlags.TELEPORT) { + ;(vnode.type as typeof TeleportImpl).remove( + vnode, + parentComponent, + parentSuspense, + optimized, + internals, + doRemove + ) + } else if ( dynamicChildren && // #1153: fast path should not be taken for non-stable (v-for) fragments (type !== Fragment || @@ -2119,17 +2128,6 @@ function baseCreateRenderer( unmountChildren(children as VNode[], parentComponent, parentSuspense) } - if (shapeFlag & ShapeFlags.TELEPORT) { - ;(vnode.type as typeof TeleportImpl).remove( - vnode, - parentComponent, - parentSuspense, - optimized, - internals, - doRemove - ) - } - if (doRemove) { remove(vnode) }