]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(suspense): avoid updating anchor if activeBranch has not been rendered to the...
authoredison <daiwei521@126.com>
Thu, 5 Sep 2024 12:56:34 +0000 (20:56 +0800)
committerGitHub <noreply@github.com>
Thu, 5 Sep 2024 12:56:34 +0000 (20:56 +0800)
close #11806

packages/runtime-core/src/components/Suspense.ts
packages/vue/__tests__/e2e/Transition.spec.ts

index c7562436179da7bb52c0ab091ed2146c74e37ace..85001f500cff8edc027cae4553dd8aa3eee4bed4 100644 (file)
@@ -566,7 +566,7 @@ function createSuspenseBoundary(
           // (got `pendingBranch.el`).
           // Therefore, after the mounting of activeBranch is completed,
           // it is necessary to get the latest anchor.
-          if (parentNode(activeBranch.el!) !== suspense.hiddenContainer) {
+          if (parentNode(activeBranch.el!) === container) {
             anchor = next(activeBranch)
           }
           unmount(activeBranch, parentComponent, suspense, true)
index 8cdda4dc63e2b02cbc782592a5557ec99c838dcd..c0863a75991be303db3781088c49a0a708dfd019 100644 (file)
@@ -2162,6 +2162,66 @@ describe('e2e: Transition', () => {
       },
       E2E_TIMEOUT,
     )
+
+    // #11806
+    test(
+      'switch between Async and Sync child when transition is not finished',
+      async () => {
+        await page().evaluate(() => {
+          const { createApp, shallowRef, h, nextTick } = (window as any).Vue
+          createApp({
+            template: `
+            <div id="container">
+              <Transition mode="out-in">
+                <Suspense>
+                  <component :is="view"/>
+                </Suspense>
+              </Transition>
+            </div>
+            <button id="toggleBtn" @click="click">button</button>
+          `,
+            setup: () => {
+              const view = shallowRef('SyncB')
+              const click = async () => {
+                view.value = 'SyncA'
+                await nextTick()
+                view.value = 'AsyncB'
+                await nextTick()
+                view.value = 'SyncB'
+              }
+              return { view, click }
+            },
+            components: {
+              SyncA: {
+                setup() {
+                  return () => h('div', 'SyncA')
+                },
+              },
+              AsyncB: {
+                async setup() {
+                  await nextTick()
+                  return () => h('div', 'AsyncB')
+                },
+              },
+              SyncB: {
+                setup() {
+                  return () => h('div', 'SyncB')
+                },
+              },
+            },
+          }).mount('#app')
+        })
+
+        expect(await html('#container')).toBe('<div>SyncB</div>')
+
+        await click('#toggleBtn')
+        await nextFrame()
+        await transitionFinish()
+        await transitionFinish()
+        expect(await html('#container')).toBe('<div class="">SyncB</div>')
+      },
+      E2E_TIMEOUT,
+    )
   })
 
   describe('transition with Teleport', () => {