Skip to content

Commit bf84ac8

Browse files
committed
fix(transition): enter/leave hook timing consistency with v2
close #1145
1 parent 9edbc27 commit bf84ac8

File tree

3 files changed

+21
-50
lines changed

3 files changed

+21
-50
lines changed

packages/runtime-dom/src/components/Transition.ts

+11-30
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@ import {
33
BaseTransitionProps,
44
h,
55
warn,
6-
FunctionalComponent,
7-
getCurrentInstance,
8-
callWithAsyncErrorHandling
6+
FunctionalComponent
97
} from '@vue/runtime-core'
108
import { isObject, toNumber, extend } from '@vue/shared'
11-
import { ErrorCodes } from 'packages/runtime-core/src/errorHandling'
129

1310
const TRANSITION = 'transition'
1411
const ANIMATION = 'animation'
@@ -94,7 +91,6 @@ export function resolveTransitionProps(
9491
return baseProps
9592
}
9693

97-
const instance = getCurrentInstance()!
9894
const durations = normalizeDuration(duration)
9995
const enterDuration = durations && durations[0]
10096
const leaveDuration = durations && durations[1]
@@ -104,14 +100,11 @@ export function resolveTransitionProps(
104100
onEnterCancelled,
105101
onLeave,
106102
onLeaveCancelled,
107-
onBeforeAppear,
108-
onAppear,
109-
onAppearCancelled
103+
onBeforeAppear = onBeforeEnter,
104+
onAppear = onEnter,
105+
onAppearCancelled = onEnterCancelled
110106
} = baseProps
111107

112-
type HookWithDone = (el: Element, done: () => void) => void
113-
type Hook = HookWithDone | ((el: Element) => void)
114-
115108
const finishEnter = (el: Element, isAppear: boolean, done?: () => void) => {
116109
removeTransitionClass(el, isAppear ? appearToClass : enterToClass)
117110
removeTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass)
@@ -124,24 +117,12 @@ export function resolveTransitionProps(
124117
done && done()
125118
}
126119

127-
// only needed for user hooks called in nextFrame
128-
// sync errors are already handled by BaseTransition
129-
const callHook = (hook: Hook | undefined, args: any[]) => {
130-
hook &&
131-
callWithAsyncErrorHandling(
132-
hook,
133-
instance,
134-
ErrorCodes.TRANSITION_HOOK,
135-
args
136-
)
137-
}
138-
139-
const makeEnterHook = (isAppear: boolean): HookWithDone => {
140-
const hook = isAppear ? onAppear : onEnter
141-
return (el, done) => {
120+
const makeEnterHook = (isAppear: boolean) => {
121+
return (el: Element, done: () => void) => {
122+
const hook = isAppear ? onAppear : onEnter
123+
const resolve = () => finishEnter(el, isAppear, done)
124+
hook && hook(el, resolve)
142125
nextFrame(() => {
143-
const resolve = () => finishEnter(el, isAppear, done)
144-
callHook(hook, [el, resolve])
145126
removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass)
146127
addTransitionClass(el, isAppear ? appearToClass : enterToClass)
147128
if (!(hook && hook.length > 1)) {
@@ -169,11 +150,10 @@ export function resolveTransitionProps(
169150
onEnter: makeEnterHook(false),
170151
onAppear: makeEnterHook(true),
171152
onLeave(el, done) {
153+
const resolve = () => finishLeave(el, done)
172154
addTransitionClass(el, leaveActiveClass)
173155
addTransitionClass(el, leaveFromClass)
174156
nextFrame(() => {
175-
const resolve = () => finishLeave(el, done)
176-
callHook(onLeave, [el, resolve])
177157
removeTransitionClass(el, leaveFromClass)
178158
addTransitionClass(el, leaveToClass)
179159
if (!(onLeave && onLeave.length > 1)) {
@@ -184,6 +164,7 @@ export function resolveTransitionProps(
184164
}
185165
}
186166
})
167+
onLeave && onLeave(el, resolve)
187168
},
188169
onEnterCancelled(el) {
189170
finishEnter(el, false)

packages/vue/__tests__/Transition.spec.ts

+7-14
Original file line numberDiff line numberDiff line change
@@ -339,15 +339,14 @@ describe('e2e: Transition', () => {
339339
])
340340
// todo test event with arguments. Note: not get dom, get object. '{}'
341341
expect(beforeLeaveSpy).toBeCalled()
342-
expect(onLeaveSpy).not.toBeCalled()
342+
expect(onLeaveSpy).toBeCalled()
343343
expect(afterLeaveSpy).not.toBeCalled()
344344
await nextFrame()
345345
expect(await classList('.test')).toStrictEqual([
346346
'test',
347347
'test-leave-active',
348348
'test-leave-to'
349349
])
350-
expect(beforeLeaveSpy).toBeCalled()
351350
expect(afterLeaveSpy).not.toBeCalled()
352351
await transitionFinish()
353352
expect(await html('#container')).toBe('<!--v-if-->')
@@ -360,15 +359,14 @@ describe('e2e: Transition', () => {
360359
'test-enter-from'
361360
])
362361
expect(beforeEnterSpy).toBeCalled()
363-
expect(onEnterSpy).not.toBeCalled()
362+
expect(onEnterSpy).toBeCalled()
364363
expect(afterEnterSpy).not.toBeCalled()
365364
await nextFrame()
366365
expect(await classList('.test')).toStrictEqual([
367366
'test',
368367
'test-enter-active',
369368
'test-enter-to'
370369
])
371-
expect(onEnterSpy).toBeCalled()
372370
expect(afterEnterSpy).not.toBeCalled()
373371
await transitionFinish()
374372
expect(await html('#container')).toBe('<div class="test">content</div>')
@@ -603,15 +601,14 @@ describe('e2e: Transition', () => {
603601
'test-appear-from'
604602
])
605603
expect(beforeAppearSpy).toBeCalled()
606-
expect(onAppearSpy).not.toBeCalled()
604+
expect(onAppearSpy).toBeCalled()
607605
expect(afterAppearSpy).not.toBeCalled()
608606
await nextFrame()
609607
expect(await classList('.test')).toStrictEqual([
610608
'test',
611609
'test-appear-active',
612610
'test-appear-to'
613611
])
614-
expect(onAppearSpy).toBeCalled()
615612
expect(afterAppearSpy).not.toBeCalled()
616613
await transitionFinish()
617614
expect(await html('#container')).toBe('<div class="test">content</div>')
@@ -628,15 +625,14 @@ describe('e2e: Transition', () => {
628625
'test-leave-from'
629626
])
630627
expect(beforeLeaveSpy).toBeCalled()
631-
expect(onLeaveSpy).not.toBeCalled()
628+
expect(onLeaveSpy).toBeCalled()
632629
expect(afterLeaveSpy).not.toBeCalled()
633630
await nextFrame()
634631
expect(await classList('.test')).toStrictEqual([
635632
'test',
636633
'test-leave-active',
637634
'test-leave-to'
638635
])
639-
expect(onLeaveSpy).toBeCalled()
640636
expect(afterLeaveSpy).not.toBeCalled()
641637
await transitionFinish()
642638
expect(await html('#container')).toBe('<!--v-if-->')
@@ -649,15 +645,14 @@ describe('e2e: Transition', () => {
649645
'test-enter-from'
650646
])
651647
expect(beforeEnterSpy).toBeCalled()
652-
expect(onEnterSpy).not.toBeCalled()
648+
expect(onEnterSpy).toBeCalled()
653649
expect(afterEnterSpy).not.toBeCalled()
654650
await nextFrame()
655651
expect(await classList('.test')).toStrictEqual([
656652
'test',
657653
'test-enter-active',
658654
'test-enter-to'
659655
])
660-
expect(onEnterSpy).toBeCalled()
661656
expect(afterEnterSpy).not.toBeCalled()
662657
await transitionFinish()
663658
expect(await html('#container')).toBe('<div class="test">content</div>')
@@ -1233,15 +1228,14 @@ describe('e2e: Transition', () => {
12331228
'test-leave-from'
12341229
])
12351230
expect(beforeLeaveSpy).toBeCalled()
1236-
expect(onLeaveSpy).not.toBeCalled()
1231+
expect(onLeaveSpy).toBeCalled()
12371232
expect(afterLeaveSpy).not.toBeCalled()
12381233
await nextFrame()
12391234
expect(await classList('.test')).toStrictEqual([
12401235
'test',
12411236
'test-leave-active',
12421237
'test-leave-to'
12431238
])
1244-
expect(beforeLeaveSpy).toBeCalled()
12451239
expect(afterLeaveSpy).not.toBeCalled()
12461240
await transitionFinish()
12471241
expect(await isVisible('.test')).toBe(false)
@@ -1254,15 +1248,14 @@ describe('e2e: Transition', () => {
12541248
'test-enter-from'
12551249
])
12561250
expect(beforeEnterSpy).toBeCalled()
1257-
expect(onEnterSpy).not.toBeCalled()
1251+
expect(onEnterSpy).toBeCalled()
12581252
expect(afterEnterSpy).not.toBeCalled()
12591253
await nextFrame()
12601254
expect(await classList('.test')).toStrictEqual([
12611255
'test',
12621256
'test-enter-active',
12631257
'test-enter-to'
12641258
])
1265-
expect(onEnterSpy).toBeCalled()
12661259
expect(afterEnterSpy).not.toBeCalled()
12671260
await transitionFinish()
12681261
expect(await html('#container')).toBe(

packages/vue/__tests__/TransitionGroup.spec.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -439,15 +439,14 @@ describe('e2e: TransitionGroup', () => {
439439
})
440440
})
441441
expect(beforeAppearSpy).toBeCalled()
442-
expect(onAppearSpy).not.toBeCalled()
442+
expect(onAppearSpy).toBeCalled()
443443
expect(afterAppearSpy).not.toBeCalled()
444444
expect(appearHtml).toBe(
445445
`<div class="test test-appear-active test-appear-from">a</div>` +
446446
`<div class="test test-appear-active test-appear-from">b</div>` +
447447
`<div class="test test-appear-active test-appear-from">c</div>`
448448
)
449449
await nextFrame()
450-
expect(onAppearSpy).toBeCalled()
451450
expect(afterAppearSpy).not.toBeCalled()
452451
expect(await html('#container')).toBe(
453452
`<div class="test test-appear-active test-appear-to">a</div>` +
@@ -470,10 +469,10 @@ describe('e2e: TransitionGroup', () => {
470469
`<div class="test test-enter-active test-enter-from">d</div>`
471470
)
472471
expect(beforeLeaveSpy).toBeCalled()
473-
expect(onLeaveSpy).not.toBeCalled()
472+
expect(onLeaveSpy).toBeCalled()
474473
expect(afterLeaveSpy).not.toBeCalled()
475474
expect(beforeEnterSpy).toBeCalled()
476-
expect(onEnterSpy).not.toBeCalled()
475+
expect(onEnterSpy).toBeCalled()
477476
expect(afterEnterSpy).not.toBeCalled()
478477
await nextFrame()
479478
expect(await html('#container')).toBe(
@@ -482,9 +481,7 @@ describe('e2e: TransitionGroup', () => {
482481
`<div class="test">c</div>` +
483482
`<div class="test test-enter-active test-enter-to">d</div>`
484483
)
485-
expect(onLeaveSpy).toBeCalled()
486484
expect(afterLeaveSpy).not.toBeCalled()
487-
expect(onEnterSpy).toBeCalled()
488485
expect(afterEnterSpy).not.toBeCalled()
489486
await transitionFinish()
490487
expect(await html('#container')).toBe(

0 commit comments

Comments
 (0)