]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(transition): fix dom transition cancel hooks not being called
authorEvan You <yyx990803@gmail.com>
Thu, 25 Jun 2020 19:00:59 +0000 (15:00 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 25 Jun 2020 19:03:58 +0000 (15:03 -0400)
packages/runtime-dom/src/components/Transition.ts
packages/vue/__tests__/Transition.spec.ts

index 5e06606ea3dffa01f6edc3b4b0fc9dee8e26941c..967a4ee568e827dbab40e36ea08087edee6cd058 100644 (file)
@@ -99,7 +99,14 @@ export function resolveTransitionProps(
   const durations = normalizeDuration(duration)
   const enterDuration = durations && durations[0]
   const leaveDuration = durations && durations[1]
-  const { appear, onBeforeEnter, onEnter, onLeave } = baseProps
+  const {
+    appear,
+    onBeforeEnter,
+    onEnter,
+    onLeave,
+    onEnterCancelled,
+    onLeaveCancelled
+  } = baseProps
 
   // is appearing
   if (appear && !instance.isMounted) {
@@ -108,9 +115,11 @@ export function resolveTransitionProps(
     enterToClass = appearToClass
   }
 
-  type Hook = (el: Element, done?: () => void) => void
+  type Hook =
+    | ((el: Element, done: () => void) => void)
+    | ((el: Element) => void)
 
-  const finishEnter: Hook = (el, done) => {
+  const finishEnter = (el: Element, done?: () => void) => {
     removeTransitionClass(el, enterToClass)
     removeTransitionClass(el, enterActiveClass)
     done && done()
@@ -120,7 +129,7 @@ export function resolveTransitionProps(
     }
   }
 
-  const finishLeave: Hook = (el, done) => {
+  const finishLeave = (el: Element, done?: () => void) => {
     removeTransitionClass(el, leaveToClass)
     removeTransitionClass(el, leaveActiveClass)
     done && done()
@@ -128,8 +137,14 @@ export function resolveTransitionProps(
 
   // only needed for user hooks called in nextFrame
   // sync errors are already handled by BaseTransition
-  function callHookWithErrorHandling(hook: Hook, args: any[]) {
-    callWithAsyncErrorHandling(hook, instance, ErrorCodes.TRANSITION_HOOK, args)
+  const callHook = (hook: Hook | undefined, args: any[]) => {
+    hook &&
+      callWithAsyncErrorHandling(
+        hook,
+        instance,
+        ErrorCodes.TRANSITION_HOOK,
+        args
+      )
   }
 
   return extend(baseProps, {
@@ -141,7 +156,7 @@ export function resolveTransitionProps(
     onEnter(el, done) {
       nextFrame(() => {
         const resolve = () => finishEnter(el, done)
-        onEnter && callHookWithErrorHandling(onEnter as Hook, [el, resolve])
+        callHook(onEnter, [el, resolve])
         removeTransitionClass(el, enterFromClass)
         addTransitionClass(el, enterToClass)
         if (!(onEnter && onEnter.length > 1)) {
@@ -158,7 +173,7 @@ export function resolveTransitionProps(
       addTransitionClass(el, leaveFromClass)
       nextFrame(() => {
         const resolve = () => finishLeave(el, done)
-        onLeave && callHookWithErrorHandling(onLeave as Hook, [el, resolve])
+        callHook(onLeave, [el, resolve])
         removeTransitionClass(el, leaveFromClass)
         addTransitionClass(el, leaveToClass)
         if (!(onLeave && onLeave.length > 1)) {
@@ -170,8 +185,14 @@ export function resolveTransitionProps(
         }
       })
     },
-    onEnterCancelled: finishEnter,
-    onLeaveCancelled: finishLeave
+    onEnterCancelled(el) {
+      finishEnter(el)
+      onEnterCancelled && onEnterCancelled(el)
+    },
+    onLeaveCancelled(el) {
+      finishLeave(el)
+      onLeaveCancelled && onLeaveCancelled(el)
+    }
   } as BaseTransitionProps<Element>)
 }
 
index 135343ef9c4a6f8494f266b2f83217d32058e03f..7242075526e7e8d665831305c39248e5fe6a50a1 100644 (file)
@@ -433,8 +433,7 @@ describe('e2e: Transition', () => {
         'test-leave-active',
         'test-leave-from'
       ])
-      // fixme
-      expect(enterCancelledSpy).not.toBeCalled()
+      expect(enterCancelledSpy).toBeCalled()
       await nextFrame()
       expect(await classList('.test')).toStrictEqual([
         'test',
@@ -1255,8 +1254,8 @@ describe('e2e: Transition', () => {
           createApp({
             template: `
             <div id="container">
-              <transition name="test">
-                <div v-show="toggle" class="test" @leave-cancelled="onLeaveCancelledSpy">content</div>
+              <transition name="test" @leave-cancelled="onLeaveCancelledSpy">
+                <div v-show="toggle" class="test">content</div>
               </transition>
             </div>
             <button id="toggleBtn" @click="click">button</button>
@@ -1290,8 +1289,7 @@ describe('e2e: Transition', () => {
           'test-enter-active',
           'test-enter-from'
         ])
-        // fixme
-        expect(onLeaveCancelledSpy).not.toBeCalled()
+        expect(onLeaveCancelledSpy).toBeCalled()
         await nextFrame()
         expect(await classList('.test')).toStrictEqual([
           'test',