Explorar el Código

fix(teleport): ensure descendent component would be unmounted correctly (#6529)

fix #6347
pupu hace 2 años
padre
commit
4162311efd

+ 25 - 0
packages/runtime-core/__tests__/components/Teleport.spec.ts

@@ -172,6 +172,31 @@ describe('renderer: teleport', () => {
     expect(serializeInner(target)).toBe('')
   })
 
+  // #6347
+  test('descendent component should be unmounted when teleport is disabled and unmounted', () => {
+    const root = nodeOps.createElement('div')
+
+    const CompWithHook = {
+      render() {
+        return [h('p'), h('p')]
+      },
+      beforeUnmount: vi.fn(),
+      unmounted: vi.fn()
+    }
+
+    render(
+      h(() => [h(Teleport, { to: null, disabled: true }, h(CompWithHook))]),
+      root
+    )
+    expect(CompWithHook.beforeUnmount).toBeCalledTimes(0)
+    expect(CompWithHook.unmounted).toBeCalledTimes(0)
+
+    render(null, root)
+
+    expect(CompWithHook.beforeUnmount).toBeCalledTimes(1)
+    expect(CompWithHook.unmounted).toBeCalledTimes(1)
+  })
+
   test('multiple teleport with same target', () => {
     const target = nodeOps.createElement('div')
     const root = nodeOps.createElement('div')

+ 14 - 15
packages/runtime-core/src/components/Teleport.ts

@@ -239,7 +239,7 @@ export const TeleportImpl = {
     parentSuspense: SuspenseBoundary | null,
     optimized: boolean,
     { um: unmount, o: { remove: hostRemove } }: RendererInternals,
-    doRemove: Boolean
+    doRemove: boolean
   ) {
     const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
 
@@ -247,20 +247,19 @@ export const TeleportImpl = {
       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++) {
-          const child = (children as VNode[])[i]
-          unmount(
-            child,
-            parentComponent,
-            parentSuspense,
-            true,
-            !!child.dynamicChildren
-          )
-        }
+    // an unmounted teleport should always unmount its children whether it's disabled or not
+    doRemove && hostRemove(anchor!)
+    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
+      const shouldRemove = doRemove || !isTeleportDisabled(props)
+      for (let i = 0; i < (children as VNode[]).length; i++) {
+        const child = (children as VNode[])[i]
+        unmount(
+          child,
+          parentComponent,
+          parentSuspense,
+          shouldRemove,
+          !!child.dynamicChildren
+        )
       }
     }
   },