]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): avoid unmount teleport's children multiple times (#3499)
authorHcySunYang <HcySunYang@outlook.com>
Mon, 29 Mar 2021 19:15:08 +0000 (03:15 +0800)
committerGitHub <noreply@github.com>
Mon, 29 Mar 2021 19:15:08 +0000 (15:15 -0400)
fix #3497

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

index f6babd9263b8a4dfbb2ddc9f0680d4d965d9df2d..8b234e2b1e6133d346aa5c0800c8b009eaeb5bf1 100644 (file)
@@ -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', () => {
       `"<div>teleported</div><span>false</span><!--v-if-->"`
     )
   })
+
+  // #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(
+      `"<!--teleport start--><!--teleport end-->"`
+    )
+    expect(serializeInner(target)).toMatchInlineSnapshot(`"<div>foo</div>"`)
+    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)
+  })
 })
index 4375dcdbf1030035bb64928df2f087becdde8ae3..5122e7a9131a5b24ff741788d9cdaa47818e2cd3 100644 (file)
@@ -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)
       }