]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-vapor): force defer mount when teleport has insertion state (#14049)
authoredison <daiwei521@126.com>
Thu, 6 Nov 2025 06:23:28 +0000 (14:23 +0800)
committerGitHub <noreply@github.com>
Thu, 6 Nov 2025 06:23:28 +0000 (14:23 +0800)
packages/runtime-vapor/__tests__/components/Teleport.spec.ts
packages/runtime-vapor/src/components/Teleport.ts

index d4282ab8a6e044e9be3561ee9d4568e47841a602..5f3324e1e35e0b60efc24df2dd718e9ff93aef4d 100644 (file)
@@ -192,6 +192,7 @@ describe('renderer: VaporTeleport', () => {
       expect(root.innerHTML).toBe(
         '<!--teleport start--><!--teleport end--><div>root 2</div>',
       )
+      await nextTick()
       expect(target.innerHTML).toBe('<div>teleported 2</div>')
     })
 
@@ -367,6 +368,7 @@ describe('renderer: VaporTeleport', () => {
       expect(root.innerHTML).toBe(
         '<!--teleport start--><!--teleport end--><div>root 2</div>',
       )
+      await nextTick()
       expect(target.innerHTML).toBe('<div>teleported 2</div>')
 
       // reload parent again by changing disabled
@@ -1255,4 +1257,41 @@ function runSharedTests(deferMode: boolean): void {
     expect(child.outerHTML).toBe(`<div>teleported</div>`)
     expect(tRefInMounted).toBe(child)
   })
+
+  test('with insertion state', async () => {
+    const root = document.createElement('div')
+    document.body.appendChild(root)
+
+    const Comp = defineVaporComponent({
+      setup() {
+        return template('content')()
+      },
+    })
+
+    const { app, mount } = define({
+      setup() {
+        const n0 = template('<div id="tt"></div>')()
+        const n4 = template('<div></div>')() as any
+        setInsertionState(n4, null, true)
+        createComponent(
+          VaporTeleport,
+          { to: () => '#tt' },
+          {
+            default: () =>
+              createComponent(Comp, null, {
+                default: () => template('content')(),
+              }),
+          },
+        )
+        return [n0, n4]
+      },
+    }).create()
+
+    mount(root)
+
+    await nextTick()
+    const target = document.querySelector('#tt')!
+    expect(target.innerHTML).toBe('content')
+    app.unmount()
+  })
 }
index 756ff5a6b58cd0b4c56509cb3c3b09cbbe1ab9d7..746798f71bf3244982d191397b92962fb4ac87b9 100644 (file)
@@ -165,7 +165,12 @@ export class TeleportFragment extends VaporFragment {
     }
     // mount into target container
     else {
-      if (isTeleportDeferred(this.resolvedProps!)) {
+      if (
+        isTeleportDeferred(this.resolvedProps!) ||
+        // force defer when the parent is not connected to the DOM,
+        // typically due to an early insertion caused by setInsertionState.
+        !this.parent!.isConnected
+      ) {
         queuePostFlushCb(mountToTarget)
       } else {
         mountToTarget()