ソースを参照

fix(Suspense): fallback should work with transition (#3968)

fix #3963
edison 5 年 前
コミット
43e2a72900

+ 2 - 1
packages/runtime-core/src/components/Suspense.ts

@@ -551,6 +551,8 @@ function createSuspenseBoundary(
       if (delayEnter) {
         activeBranch!.transition!.afterLeave = mountFallback
       }
+      suspense.isInFallback = true
+
       // unmount current active branch
       unmount(
         activeBranch!,
@@ -559,7 +561,6 @@ function createSuspenseBoundary(
         true // shouldRemove
       )
 
-      suspense.isInFallback = true
       if (!delayEnter) {
         mountFallback()
       }

+ 63 - 0
packages/vue/__tests__/Transition.spec.ts

@@ -1325,6 +1325,69 @@ describe('e2e: Transition', () => {
       },
       E2E_TIMEOUT
     )
+
+    // #3963
+    test(
+      'Suspense fallback should work with transition',
+      async () => {
+        await page().evaluate(() => {
+          const { createApp, shallowRef, h } = (window as any).Vue
+
+          const One = {
+            template: `<div>{{ msg }}</div>`,
+            setup() {
+              return new Promise(_resolve => {
+                // @ts-ignore
+                window.resolve = () =>
+                  _resolve({
+                    msg: 'success'
+                  })
+              })
+            }
+          }
+
+          createApp({
+            template: `
+              <div id="container">
+                <transition mode="out-in">
+                  <Suspense :timeout="0">
+                    <template #default>
+                      <component :is="view" />
+                    </template>
+                    <template #fallback>
+                      <div>Loading...</div>
+                    </template>
+                  </Suspense>
+                </transition>
+              </div>
+              <button id="toggleBtn" @click="click">button</button>
+            `,
+            setup: () => {
+              const view = shallowRef(null)
+              const click = () => {
+                view.value = view.value ? null : h(One)
+              }
+              return { view, click }
+            }
+          }).mount('#app')
+        })
+
+        expect(await html('#container')).toBe('<!---->')
+
+        await click('#toggleBtn')
+        await nextFrame()
+        expect(await html('#container')).toBe('<div class="">Loading...</div>')
+
+        await page().evaluate(() => {
+          // @ts-ignore
+          window.resolve()
+        })
+
+        await transitionFinish(duration * 2)
+        expect(await html('#container')).toBe('<div class="">success</div>')
+      },
+      E2E_TIMEOUT
+    )
   })
 
   describe('transition with v-show', () => {