Skip to content

Commit

Permalink
fix(transition): enter/leave hook timing consistency with v2
Browse files Browse the repository at this point in the history
close #1145
  • Loading branch information
yyx990803 committed Jun 25, 2020
1 parent 9edbc27 commit bf84ac8
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 50 deletions.
41 changes: 11 additions & 30 deletions packages/runtime-dom/src/components/Transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ import {
BaseTransitionProps,
h,
warn,
FunctionalComponent,
getCurrentInstance,
callWithAsyncErrorHandling
FunctionalComponent
} from '@vue/runtime-core'
import { isObject, toNumber, extend } from '@vue/shared'
import { ErrorCodes } from 'packages/runtime-core/src/errorHandling'

const TRANSITION = 'transition'
const ANIMATION = 'animation'
Expand Down Expand Up @@ -94,7 +91,6 @@ export function resolveTransitionProps(
return baseProps
}

const instance = getCurrentInstance()!
const durations = normalizeDuration(duration)
const enterDuration = durations && durations[0]
const leaveDuration = durations && durations[1]
Expand All @@ -104,14 +100,11 @@ export function resolveTransitionProps(
onEnterCancelled,
onLeave,
onLeaveCancelled,
onBeforeAppear,
onAppear,
onAppearCancelled
onBeforeAppear = onBeforeEnter,
onAppear = onEnter,
onAppearCancelled = onEnterCancelled
} = baseProps

type HookWithDone = (el: Element, done: () => void) => void
type Hook = HookWithDone | ((el: Element) => void)

const finishEnter = (el: Element, isAppear: boolean, done?: () => void) => {
removeTransitionClass(el, isAppear ? appearToClass : enterToClass)
removeTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass)
Expand All @@ -124,24 +117,12 @@ export function resolveTransitionProps(
done && done()
}

// only needed for user hooks called in nextFrame
// sync errors are already handled by BaseTransition
const callHook = (hook: Hook | undefined, args: any[]) => {
hook &&
callWithAsyncErrorHandling(
hook,
instance,
ErrorCodes.TRANSITION_HOOK,
args
)
}

const makeEnterHook = (isAppear: boolean): HookWithDone => {
const hook = isAppear ? onAppear : onEnter
return (el, done) => {
const makeEnterHook = (isAppear: boolean) => {
return (el: Element, done: () => void) => {
const hook = isAppear ? onAppear : onEnter
const resolve = () => finishEnter(el, isAppear, done)
hook && hook(el, resolve)
nextFrame(() => {
const resolve = () => finishEnter(el, isAppear, done)
callHook(hook, [el, resolve])
removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass)
addTransitionClass(el, isAppear ? appearToClass : enterToClass)
if (!(hook && hook.length > 1)) {
Expand Down Expand Up @@ -169,11 +150,10 @@ export function resolveTransitionProps(
onEnter: makeEnterHook(false),
onAppear: makeEnterHook(true),
onLeave(el, done) {
const resolve = () => finishLeave(el, done)
addTransitionClass(el, leaveActiveClass)
addTransitionClass(el, leaveFromClass)
nextFrame(() => {
const resolve = () => finishLeave(el, done)
callHook(onLeave, [el, resolve])
removeTransitionClass(el, leaveFromClass)
addTransitionClass(el, leaveToClass)
if (!(onLeave && onLeave.length > 1)) {
Expand All @@ -184,6 +164,7 @@ export function resolveTransitionProps(
}
}
})
onLeave && onLeave(el, resolve)
},
onEnterCancelled(el) {
finishEnter(el, false)
Expand Down
21 changes: 7 additions & 14 deletions packages/vue/__tests__/Transition.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,15 +339,14 @@ describe('e2e: Transition', () => {
])
// todo test event with arguments. Note: not get dom, get object. '{}'
expect(beforeLeaveSpy).toBeCalled()
expect(onLeaveSpy).not.toBeCalled()
expect(onLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-leave-active',
'test-leave-to'
])
expect(beforeLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe('<!--v-if-->')
Expand All @@ -360,15 +359,14 @@ describe('e2e: Transition', () => {
'test-enter-from'
])
expect(beforeEnterSpy).toBeCalled()
expect(onEnterSpy).not.toBeCalled()
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-enter-active',
'test-enter-to'
])
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe('<div class="test">content</div>')
Expand Down Expand Up @@ -603,15 +601,14 @@ describe('e2e: Transition', () => {
'test-appear-from'
])
expect(beforeAppearSpy).toBeCalled()
expect(onAppearSpy).not.toBeCalled()
expect(onAppearSpy).toBeCalled()
expect(afterAppearSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-appear-active',
'test-appear-to'
])
expect(onAppearSpy).toBeCalled()
expect(afterAppearSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe('<div class="test">content</div>')
Expand All @@ -628,15 +625,14 @@ describe('e2e: Transition', () => {
'test-leave-from'
])
expect(beforeLeaveSpy).toBeCalled()
expect(onLeaveSpy).not.toBeCalled()
expect(onLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-leave-active',
'test-leave-to'
])
expect(onLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe('<!--v-if-->')
Expand All @@ -649,15 +645,14 @@ describe('e2e: Transition', () => {
'test-enter-from'
])
expect(beforeEnterSpy).toBeCalled()
expect(onEnterSpy).not.toBeCalled()
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-enter-active',
'test-enter-to'
])
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe('<div class="test">content</div>')
Expand Down Expand Up @@ -1233,15 +1228,14 @@ describe('e2e: Transition', () => {
'test-leave-from'
])
expect(beforeLeaveSpy).toBeCalled()
expect(onLeaveSpy).not.toBeCalled()
expect(onLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-leave-active',
'test-leave-to'
])
expect(beforeLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
await transitionFinish()
expect(await isVisible('.test')).toBe(false)
Expand All @@ -1254,15 +1248,14 @@ describe('e2e: Transition', () => {
'test-enter-from'
])
expect(beforeEnterSpy).toBeCalled()
expect(onEnterSpy).not.toBeCalled()
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'test-enter-active',
'test-enter-to'
])
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe(
Expand Down
9 changes: 3 additions & 6 deletions packages/vue/__tests__/TransitionGroup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,15 +439,14 @@ describe('e2e: TransitionGroup', () => {
})
})
expect(beforeAppearSpy).toBeCalled()
expect(onAppearSpy).not.toBeCalled()
expect(onAppearSpy).toBeCalled()
expect(afterAppearSpy).not.toBeCalled()
expect(appearHtml).toBe(
`<div class="test test-appear-active test-appear-from">a</div>` +
`<div class="test test-appear-active test-appear-from">b</div>` +
`<div class="test test-appear-active test-appear-from">c</div>`
)
await nextFrame()
expect(onAppearSpy).toBeCalled()
expect(afterAppearSpy).not.toBeCalled()
expect(await html('#container')).toBe(
`<div class="test test-appear-active test-appear-to">a</div>` +
Expand All @@ -470,10 +469,10 @@ describe('e2e: TransitionGroup', () => {
`<div class="test test-enter-active test-enter-from">d</div>`
)
expect(beforeLeaveSpy).toBeCalled()
expect(onLeaveSpy).not.toBeCalled()
expect(onLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
expect(beforeEnterSpy).toBeCalled()
expect(onEnterSpy).not.toBeCalled()
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await nextFrame()
expect(await html('#container')).toBe(
Expand All @@ -482,9 +481,7 @@ describe('e2e: TransitionGroup', () => {
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-to">d</div>`
)
expect(onLeaveSpy).toBeCalled()
expect(afterLeaveSpy).not.toBeCalled()
expect(onEnterSpy).toBeCalled()
expect(afterEnterSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe(
Expand Down

0 comments on commit bf84ac8

Please sign in to comment.