Bladeren bron

fix(Transition): handle leave immediatily done in out-in mode

daiwei 1 jaar geleden
bovenliggende
commit
43d5e4d2a1

+ 2 - 2
packages/runtime-core/src/components/BaseTransition.ts

@@ -20,7 +20,7 @@ import { PatchFlags, ShapeFlags, isArray, isFunction } from '@vue/shared'
 import { onBeforeUnmount, onMounted } from '../apiLifecycle'
 import { onBeforeUnmount, onMounted } from '../apiLifecycle'
 import { isTeleport } from './Teleport'
 import { isTeleport } from './Teleport'
 import type { RendererElement } from '../renderer'
 import type { RendererElement } from '../renderer'
-import { SchedulerJobFlags } from '../scheduler'
+import { SchedulerJobFlags, queueJob } from '../scheduler'
 
 
 type Hook<T = () => void> = T | T[]
 type Hook<T = () => void> = T | T[]
 
 
@@ -225,7 +225,7 @@ const BaseTransitionImpl: ComponentOptions = {
             // #6835
             // #6835
             // it also needs to be updated when active is undefined
             // it also needs to be updated when active is undefined
             if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {
             if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {
-              instance.update()
+              queueJob(instance.update)
             }
             }
             delete leavingHooks.afterLeave
             delete leavingHooks.afterLeave
           }
           }

+ 46 - 0
packages/vue/__tests__/e2e/Transition.spec.ts

@@ -767,6 +767,52 @@ describe('e2e: Transition', () => {
       E2E_TIMEOUT,
       E2E_TIMEOUT,
     )
     )
 
 
+    test(
+      'onLeave event immediately done (out-in mode)',
+      async () => {
+        const onLeaveSpy = vi.fn()
+        await page().exposeFunction('onLeaveSpy', onLeaveSpy)
+
+        await page().evaluate(async () => {
+          const { onLeaveSpy } = window as any
+          const { createApp, ref } = (window as any).Vue
+          createApp({
+            template: `
+              <div id="container">
+                <transition mode="out-in" @leave="onLeave">
+                  <div v-if="toggle">True</div>
+                  <div v-else>False</div>
+                </transition>
+              </div>
+              <button id="toggleBtn" @click="click">button</button>
+            `,
+            setup: () => {
+              const toggle = ref(true)
+              function onLeave(el: Element, done: Function) {
+                onLeaveSpy()
+                // immediately done
+                done()
+              }
+              const click = () => (toggle.value = !toggle.value)
+              return {
+                toggle,
+                click,
+                onLeave,
+              }
+            },
+          }).mount('#app')
+        })
+
+        expect(await html('#container')).toBe('<div>True</div>')
+
+        await click('#toggleBtn')
+        await transitionFinish()
+        expect(onLeaveSpy).toBeCalled()
+        expect(await html('#container')).toBe('<div class="">False</div>')
+      },
+      E2E_TIMEOUT,
+    )
+
     test(
     test(
       'css: false',
       'css: false',
       async () => {
       async () => {