From 7762beeb796bc934b9dbd6a6e20ee990b30c512c Mon Sep 17 00:00:00 2001 From: luwuer Date: Thu, 12 Nov 2020 14:17:46 +0800 Subject: [PATCH 1/4] feat(runtime-dom): transition component effect on visibility (#2531) --- .../runtime-dom/src/components/Transition.ts | 3 +- packages/vue/__tests__/Transition.spec.ts | 47 ++----------------- .../vue/__tests__/TransitionGroup.spec.ts | 26 +++++----- 3 files changed, 18 insertions(+), 58 deletions(-) diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index b969b69736b..ec92a3ebfcc 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -123,6 +123,7 @@ export function resolveTransitionProps( const resolve = () => finishEnter(el, isAppear, done) hook && hook(el, resolve) nextFrame(() => { + addTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass) removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass) addTransitionClass(el, isAppear ? appearToClass : enterToClass) if (!(hook && hook.length > 1)) { @@ -135,12 +136,10 @@ export function resolveTransitionProps( return extend(baseProps, { onBeforeEnter(el) { onBeforeEnter && onBeforeEnter(el) - addTransitionClass(el, enterActiveClass) addTransitionClass(el, enterFromClass) }, onBeforeAppear(el) { onBeforeAppear && onBeforeAppear(el) - addTransitionClass(el, appearActiveClass) addTransitionClass(el, appearFromClass) }, onEnter: makeEnterHook(false), diff --git a/packages/vue/__tests__/Transition.spec.ts b/packages/vue/__tests__/Transition.spec.ts index 93959e45d50..2b7aa4c1786 100644 --- a/packages/vue/__tests__/Transition.spec.ts +++ b/packages/vue/__tests__/Transition.spec.ts @@ -74,7 +74,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'v-enter-active', 'v-enter-from' ]) await nextFrame() @@ -130,7 +129,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -191,7 +189,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'hello-active', 'hello-from' ]) await nextFrame() @@ -253,7 +250,6 @@ describe('e2e: Transition', () => { }) expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'changed-enter-active', 'changed-enter-from' ]) await nextFrame() @@ -353,7 +349,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) expect(beforeEnterSpy).toBeCalled() @@ -408,7 +403,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -464,11 +458,7 @@ describe('e2e: Transition', () => { }) }) // appear - expect(appearClass).toStrictEqual([ - 'test', - 'test-appear-active', - 'test-appear-from' - ]) + expect(appearClass).toStrictEqual(['test', 'test-appear-from']) await nextFrame() expect(await classList('.test')).toStrictEqual([ 'test', @@ -496,7 +486,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -593,11 +582,7 @@ describe('e2e: Transition', () => { }) }) // appear - expect(appearClass).toStrictEqual([ - 'test', - 'test-appear-active', - 'test-appear-from' - ]) + expect(appearClass).toStrictEqual(['test', 'test-appear-from']) expect(beforeAppearSpy).toBeCalled() expect(onAppearSpy).toBeCalled() expect(afterAppearSpy).not.toBeCalled() @@ -639,7 +624,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) expect(beforeEnterSpy).toBeCalled() @@ -770,7 +754,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ - 'noop-enter-active', 'noop-enter-from' ]) await nextFrame() @@ -817,7 +800,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ - 'test-anim-enter-active', 'test-anim-enter-from' ]) await nextFrame() @@ -872,7 +854,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ - 'test-anim-long-enter-active', 'test-anim-long-enter-from' ]) await nextFrame() @@ -947,7 +928,6 @@ describe('e2e: Transition', () => { // enter expect(await svgTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1006,7 +986,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1063,7 +1042,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1175,11 +1153,7 @@ describe('e2e: Transition', () => { .querySelector('#container div')! .className.split(/\s+/g) }) - expect(enterClass).toStrictEqual([ - 'test', - 'v-enter-active', - 'v-enter-from' - ]) + expect(enterClass).toStrictEqual(['test', 'v-enter-from']) expect(onEnterSpy).toBeCalledTimes(2) await nextFrame() expect(await classList('.test')).toStrictEqual([ @@ -1237,7 +1211,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'v-enter-active', 'v-enter-from' ]) await nextFrame() @@ -1361,7 +1334,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1462,7 +1434,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) expect(beforeEnterSpy).toBeCalled() @@ -1528,7 +1499,6 @@ describe('e2e: Transition', () => { // cancel (enter) expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) expect(onLeaveCancelledSpy).toBeCalled() @@ -1575,11 +1545,7 @@ describe('e2e: Transition', () => { }) }) // appear - expect(appearClass).toStrictEqual([ - 'test', - 'test-appear-active', - 'test-appear-from' - ]) + expect(appearClass).toStrictEqual(['test', 'test-appear-from']) await nextFrame() expect(await classList('.test')).toStrictEqual([ 'test', @@ -1607,7 +1573,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1684,7 +1649,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1740,7 +1704,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1796,7 +1759,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1855,7 +1817,6 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-enter-active', 'test-enter-from' ]) await nextFrame() diff --git a/packages/vue/__tests__/TransitionGroup.spec.ts b/packages/vue/__tests__/TransitionGroup.spec.ts index dee092ff677..68bdbe68caa 100644 --- a/packages/vue/__tests__/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/TransitionGroup.spec.ts @@ -55,8 +55,8 @@ describe('e2e: TransitionGroup', () => { `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) await nextFrame() expect(await html('#container')).toBe( @@ -153,7 +153,7 @@ describe('e2e: TransitionGroup', () => { `
a
` + `
b
` + `
c
` + - `
d
` + `
d
` ) await nextFrame() expect(await html('#container')).toBe( @@ -202,9 +202,9 @@ describe('e2e: TransitionGroup', () => { }) // appear expect(appearHtml).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await nextFrame() expect(await html('#container')).toBe( @@ -224,8 +224,8 @@ describe('e2e: TransitionGroup', () => { `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) await nextFrame() expect(await html('#container')).toBe( @@ -275,7 +275,7 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` + `
c
` @@ -440,9 +440,9 @@ describe('e2e: TransitionGroup', () => { expect(onAppearSpy).toBeCalled() expect(afterAppearSpy).not.toBeCalled() expect(appearHtml).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await nextFrame() expect(afterAppearSpy).not.toBeCalled() @@ -464,7 +464,7 @@ describe('e2e: TransitionGroup', () => { `
a
` + `
b
` + `
c
` + - `
d
` + `
d
` ) expect(beforeLeaveSpy).toBeCalled() expect(onLeaveSpy).toBeCalled() From 0987bb5d6d9dd63ea6e949ae535ea3998a0d0859 Mon Sep 17 00:00:00 2001 From: luwuer Date: Thu, 12 Nov 2020 19:48:15 +0800 Subject: [PATCH 2/4] fix(runtime-dom): transition component does not work with "*-leave-from" (#2593) --- .../runtime-dom/src/components/Transition.ts | 2 +- packages/vue/__tests__/Transition.spec.ts | 34 ++++++------------- .../vue/__tests__/TransitionGroup.spec.ts | 12 +++---- 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index ec92a3ebfcc..b0feb7dafa6 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -146,9 +146,9 @@ export function resolveTransitionProps( onAppear: makeEnterHook(true), onLeave(el, done) { const resolve = () => finishLeave(el, done) - addTransitionClass(el, leaveActiveClass) addTransitionClass(el, leaveFromClass) nextFrame(() => { + addTransitionClass(el, leaveActiveClass) removeTransitionClass(el, leaveFromClass) addTransitionClass(el, leaveToClass) if (!(onLeave && onLeave.length > 1)) { diff --git a/packages/vue/__tests__/Transition.spec.ts b/packages/vue/__tests__/Transition.spec.ts index 2b7aa4c1786..cca0eee74d6 100644 --- a/packages/vue/__tests__/Transition.spec.ts +++ b/packages/vue/__tests__/Transition.spec.ts @@ -59,7 +59,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'v-leave-active', 'v-leave-from' ]) await nextFrame() @@ -114,7 +113,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -174,7 +172,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'bye-active', 'bye-from' ]) await nextFrame() @@ -232,7 +229,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -328,7 +324,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) // todo test event with arguments. Note: not get dom, get object. '{}' @@ -415,7 +410,6 @@ describe('e2e: Transition', () => { // cancel (leave) expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) expect(enterCancelledSpy).toBeCalled() @@ -471,7 +465,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -604,7 +597,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) expect(beforeLeaveSpy).toBeCalled() @@ -746,7 +738,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ - 'noop-leave-active', 'noop-leave-from' ]) await nextFrame() @@ -787,7 +778,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ - 'test-anim-leave-active', 'test-anim-leave-from' ]) await nextFrame() @@ -834,7 +824,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ - 'test-anim-long-leave-active', 'test-anim-long-leave-from' ]) await nextFrame() @@ -913,7 +902,6 @@ describe('e2e: Transition', () => { // leave expect(await svgTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -971,7 +959,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1060,7 +1047,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1127,7 +1113,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'v-leave-active', 'v-leave-from' ]) expect(onLeaveSpy).toBeCalledTimes(1) @@ -1196,7 +1181,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'v-leave-active', 'v-leave-from' ]) await nextFrame() @@ -1276,15 +1260,25 @@ describe('e2e: Transition', () => { // leave await classWhenTransitionStart() + // component one [before enter] await nextFrame() + // component one [enter] expect(await html('#container')).toBe( '
one
' ) await transitionFinish() + // component one [finish] + // component two [before enter] + expect(await html('#container')).toBe( + '
two
' + ) + await nextFrame() + // component two [enter] expect(await html('#container')).toBe( '
two
' ) await transitionFinish() + // component two [finish] expect(await html('#container')).toBe('
two
') }, E2E_TIMEOUT @@ -1319,7 +1313,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1414,7 +1407,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) expect(beforeLeaveSpy).toBeCalled() @@ -1486,7 +1478,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1558,7 +1549,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1634,7 +1624,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1689,7 +1678,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1744,7 +1732,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1802,7 +1789,6 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'test-leave-active', 'test-leave-from' ]) await nextFrame() diff --git a/packages/vue/__tests__/TransitionGroup.spec.ts b/packages/vue/__tests__/TransitionGroup.spec.ts index 68bdbe68caa..139a5ff6173 100644 --- a/packages/vue/__tests__/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/TransitionGroup.spec.ts @@ -106,9 +106,9 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + - `
c
` + `
c
` ) await nextFrame() expect(await html('#container')).toBe( @@ -150,7 +150,7 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + `
c
` + `
d
` @@ -278,14 +278,14 @@ describe('e2e: TransitionGroup', () => { `
d
` + `
b
` + `
a
` + - `
c
` + `
c
` ) await nextFrame() expect(await html('#container')).toBe( `
d
` + `
b
` + `
a
` + - `
c
` + `
c
` ) await transitionFinish(duration * 2) expect(await html('#container')).toBe( @@ -461,7 +461,7 @@ describe('e2e: TransitionGroup', () => { // enter + leave expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + `
c
` + `
d
` From 3b4198ee058943df6a1d3d4559af3b754cbacecc Mon Sep 17 00:00:00 2001 From: luwuer Date: Wed, 2 Dec 2020 17:11:57 +0800 Subject: [PATCH 3/4] feat(runtime-dom): transition component disable transition property on the first frame (#2531, #2586) --- .../runtime-dom/src/components/Transition.ts | 22 ++- packages/vue/__tests__/Transition.spec.ts | 186 ++++++++++++++---- .../vue/__tests__/TransitionGroup.spec.ts | 128 ++++++------ 3 files changed, 228 insertions(+), 108 deletions(-) diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index b0feb7dafa6..46924117b1d 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -123,7 +123,7 @@ export function resolveTransitionProps( const resolve = () => finishEnter(el, isAppear, done) hook && hook(el, resolve) nextFrame(() => { - addTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass) + enableTransition(el) removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass) addTransitionClass(el, isAppear ? appearToClass : enterToClass) if (!(hook && hook.length > 1)) { @@ -133,22 +133,40 @@ export function resolveTransitionProps( } } + // see issue #2531, #2593 + let cacheTransition: string + const disableTransition = (el: Element) => { + const style = (el as HTMLElement).style + cacheTransition = style.transition + style.transitionProperty = 'none' + } + + const enableTransition = (el: Element) => { + ;(el as HTMLElement).style.transition = cacheTransition + } + return extend(baseProps, { onBeforeEnter(el) { onBeforeEnter && onBeforeEnter(el) + addTransitionClass(el, enterActiveClass) addTransitionClass(el, enterFromClass) + disableTransition(el) }, onBeforeAppear(el) { onBeforeAppear && onBeforeAppear(el) + addTransitionClass(el, appearActiveClass) addTransitionClass(el, appearFromClass) + disableTransition(el) }, onEnter: makeEnterHook(false), onAppear: makeEnterHook(true), onLeave(el, done) { const resolve = () => finishLeave(el, done) + addTransitionClass(el, leaveActiveClass) addTransitionClass(el, leaveFromClass) + disableTransition(el) nextFrame(() => { - addTransitionClass(el, leaveActiveClass) + enableTransition(el) removeTransitionClass(el, leaveFromClass) addTransitionClass(el, leaveToClass) if (!(onLeave && onLeave.length > 1)) { diff --git a/packages/vue/__tests__/Transition.spec.ts b/packages/vue/__tests__/Transition.spec.ts index cca0eee74d6..2d3efcc595e 100644 --- a/packages/vue/__tests__/Transition.spec.ts +++ b/packages/vue/__tests__/Transition.spec.ts @@ -59,6 +59,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'v-leave-active', 'v-leave-from' ]) await nextFrame() @@ -73,6 +74,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'v-enter-active', 'v-enter-from' ]) await nextFrame() @@ -82,7 +84,9 @@ describe('e2e: Transition', () => { 'v-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -113,6 +117,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -127,6 +132,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -136,7 +142,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -172,6 +180,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'bye-active', 'bye-from' ]) await nextFrame() @@ -186,6 +195,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'hello-active', 'hello-from' ]) await nextFrame() @@ -195,7 +205,9 @@ describe('e2e: Transition', () => { 'hello-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -229,6 +241,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -246,6 +259,7 @@ describe('e2e: Transition', () => { }) expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'changed-enter-active', 'changed-enter-from' ]) await nextFrame() @@ -255,7 +269,9 @@ describe('e2e: Transition', () => { 'changed-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -324,6 +340,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) // todo test event with arguments. Note: not get dom, get object. '{}' @@ -344,6 +361,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) expect(beforeEnterSpy).toBeCalled() @@ -357,7 +375,9 @@ describe('e2e: Transition', () => { ]) expect(afterEnterSpy).not.toBeCalled() await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) expect(afterEnterSpy).toBeCalled() }, E2E_TIMEOUT @@ -398,6 +418,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -410,6 +431,7 @@ describe('e2e: Transition', () => { // cancel (leave) expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) expect(enterCancelledSpy).toBeCalled() @@ -452,7 +474,11 @@ describe('e2e: Transition', () => { }) }) // appear - expect(appearClass).toStrictEqual(['test', 'test-appear-from']) + expect(appearClass).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-from' + ]) await nextFrame() expect(await classList('.test')).toStrictEqual([ 'test', @@ -460,11 +486,14 @@ describe('e2e: Transition', () => { 'test-appear-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -479,6 +508,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -488,7 +518,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -575,7 +607,11 @@ describe('e2e: Transition', () => { }) }) // appear - expect(appearClass).toStrictEqual(['test', 'test-appear-from']) + expect(appearClass).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-from' + ]) expect(beforeAppearSpy).toBeCalled() expect(onAppearSpy).toBeCalled() expect(afterAppearSpy).not.toBeCalled() @@ -587,7 +623,9 @@ describe('e2e: Transition', () => { ]) expect(afterAppearSpy).not.toBeCalled() await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) expect(afterAppearSpy).toBeCalled() expect(beforeEnterSpy).not.toBeCalled() @@ -597,6 +635,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) expect(beforeLeaveSpy).toBeCalled() @@ -616,6 +655,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) expect(beforeEnterSpy).toBeCalled() @@ -629,7 +669,9 @@ describe('e2e: Transition', () => { ]) expect(afterEnterSpy).not.toBeCalled() await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) expect(afterEnterSpy).toBeCalled() }, E2E_TIMEOUT @@ -738,6 +780,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ + 'noop-leave-active', 'noop-leave-from' ]) await nextFrame() @@ -745,10 +788,13 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ + 'noop-enter-active', 'noop-enter-from' ]) await nextFrame() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -778,6 +824,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ + 'test-anim-leave-active', 'test-anim-leave-from' ]) await nextFrame() @@ -790,6 +837,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ + 'test-anim-enter-active', 'test-anim-enter-from' ]) await nextFrame() @@ -798,7 +846,9 @@ describe('e2e: Transition', () => { 'test-anim-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -824,6 +874,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ + 'test-anim-long-leave-active', 'test-anim-long-leave-from' ]) await nextFrame() @@ -843,6 +894,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ + 'test-anim-long-enter-active', 'test-anim-long-enter-from' ]) await nextFrame() @@ -858,7 +910,9 @@ describe('e2e: Transition', () => { 'test-anim-long-enter-to' ]) await transitionFinish(duration * 2) - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -902,6 +956,7 @@ describe('e2e: Transition', () => { // leave expect(await svgTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -916,6 +971,7 @@ describe('e2e: Transition', () => { // enter expect(await svgTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -926,7 +982,7 @@ describe('e2e: Transition', () => { ]) await transitionFinish() expect(await html('#container')).toBe( - '' + '' ) }, E2E_TIMEOUT @@ -959,6 +1015,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -973,6 +1030,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -982,7 +1040,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -1029,6 +1089,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1038,7 +1099,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
two
') + expect(await html('#container')).toBe( + '
two
' + ) // change view -> 'one' await page().evaluate(() => { @@ -1047,6 +1110,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1105,14 +1169,17 @@ describe('e2e: Transition', () => { expect(onEnterSpy).toBeCalledTimes(1) await nextFrame() expect(await html('#container')).toBe( - '
content
' + '
content
' ) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'v-leave-active', 'v-leave-from' ]) expect(onLeaveSpy).toBeCalledTimes(1) @@ -1138,7 +1205,11 @@ describe('e2e: Transition', () => { .querySelector('#container div')! .className.split(/\s+/g) }) - expect(enterClass).toStrictEqual(['test', 'v-enter-from']) + expect(enterClass).toStrictEqual([ + 'test', + 'v-enter-active', + 'v-enter-from' + ]) expect(onEnterSpy).toBeCalledTimes(2) await nextFrame() expect(await classList('.test')).toStrictEqual([ @@ -1147,7 +1218,9 @@ describe('e2e: Transition', () => { 'v-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -1181,6 +1254,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'v-leave-active', 'v-leave-from' ]) await nextFrame() @@ -1195,6 +1269,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'v-enter-active', 'v-enter-from' ]) await nextFrame() @@ -1204,7 +1279,9 @@ describe('e2e: Transition', () => { 'v-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -1253,33 +1330,28 @@ describe('e2e: Transition', () => { await nextFrame() expect(await html('#container')).toBe( - '
one
' + '
one
' ) await transitionFinish() - expect(await html('#container')).toBe('
one
') + expect(await html('#container')).toBe( + '
one
' + ) // leave await classWhenTransitionStart() - // component one [before enter] await nextFrame() - // component one [enter] expect(await html('#container')).toBe( - '
one
' + '
one
' ) await transitionFinish() - // component one [finish] - // component two [before enter] - expect(await html('#container')).toBe( - '
two
' - ) await nextFrame() - // component two [enter] expect(await html('#container')).toBe( - '
two
' + '
two
' ) await transitionFinish() - // component two [finish] - expect(await html('#container')).toBe('
two
') + expect(await html('#container')).toBe( + '
two
' + ) }, E2E_TIMEOUT ) @@ -1313,6 +1385,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1327,6 +1400,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1407,6 +1481,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) expect(beforeLeaveSpy).toBeCalled() @@ -1426,6 +1501,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) expect(beforeEnterSpy).toBeCalled() @@ -1478,6 +1554,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1490,6 +1567,7 @@ describe('e2e: Transition', () => { // cancel (enter) expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) expect(onLeaveCancelledSpy).toBeCalled() @@ -1536,7 +1614,11 @@ describe('e2e: Transition', () => { }) }) // appear - expect(appearClass).toStrictEqual(['test', 'test-appear-from']) + expect(appearClass).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-from' + ]) await nextFrame() expect(await classList('.test')).toStrictEqual([ 'test', @@ -1544,11 +1626,14 @@ describe('e2e: Transition', () => { 'test-appear-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1563,6 +1648,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1624,6 +1710,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1638,6 +1725,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1647,7 +1735,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish(duration * 2) - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -1678,6 +1768,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1692,6 +1783,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1701,7 +1793,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish(duration * 2) - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -1732,6 +1826,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1746,6 +1841,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1755,7 +1851,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) @@ -1789,6 +1887,7 @@ describe('e2e: Transition', () => { // leave expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-leave-active', 'test-leave-from' ]) await nextFrame() @@ -1803,6 +1902,7 @@ describe('e2e: Transition', () => { // enter expect(await classWhenTransitionStart()).toStrictEqual([ 'test', + 'test-enter-active', 'test-enter-from' ]) await nextFrame() @@ -1812,7 +1912,9 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish(200) - expect(await html('#container')).toBe('
content
') + expect(await html('#container')).toBe( + '
content
' + ) }, E2E_TIMEOUT ) diff --git a/packages/vue/__tests__/TransitionGroup.spec.ts b/packages/vue/__tests__/TransitionGroup.spec.ts index 139a5ff6173..9c82d6700c2 100644 --- a/packages/vue/__tests__/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/TransitionGroup.spec.ts @@ -55,24 +55,24 @@ describe('e2e: TransitionGroup', () => { `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) await nextFrame() expect(await html('#container')).toBe( `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) await transitionFinish() expect(await html('#container')).toBe( `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) }, E2E_TIMEOUT @@ -106,15 +106,15 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + - `
c
` + `
c
` ) await nextFrame() expect(await html('#container')).toBe( - `
a
` + + `
a
` + `
b
` + - `
c
` + `
c
` ) await transitionFinish() expect(await html('#container')).toBe(`
b
`) @@ -150,23 +150,23 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + `
c
` + - `
d
` + `
d
` ) await nextFrame() expect(await html('#container')).toBe( - `
a
` + + `
a
` + `
b
` + `
c
` + - `
d
` + `
d
` ) await transitionFinish() expect(await html('#container')).toBe( `
b
` + `
c
` + - `
d
` + `
d
` ) }, E2E_TIMEOUT @@ -202,46 +202,46 @@ describe('e2e: TransitionGroup', () => { }) // appear expect(appearHtml).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await nextFrame() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await transitionFinish() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) // enter expect(await htmlWhenTransitionStart()).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + - `
e
` + `
a
` + + `
b
` + + `
c
` + + `
d
` + + `
e
` ) await nextFrame() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + - `
e
` + `
a
` + + `
b
` + + `
c
` + + `
d
` + + `
e
` ) await transitionFinish() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + - `
e
` + `
a
` + + `
b
` + + `
c
` + + `
d
` + + `
e
` ) }, E2E_TIMEOUT @@ -275,21 +275,21 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` + - `
c
` + `
c
` ) await nextFrame() expect(await html('#container')).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` + - `
c
` + `
c
` ) await transitionFinish(duration * 2) expect(await html('#container')).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` ) @@ -440,31 +440,31 @@ describe('e2e: TransitionGroup', () => { expect(onAppearSpy).toBeCalled() expect(afterAppearSpy).not.toBeCalled() expect(appearHtml).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await nextFrame() expect(afterAppearSpy).not.toBeCalled() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await transitionFinish() expect(afterAppearSpy).toBeCalled() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) // enter + leave expect(await htmlWhenTransitionStart()).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + `
a
` + + `
b
` + + `
c
` + + `
d
` ) expect(beforeLeaveSpy).toBeCalled() expect(onLeaveSpy).toBeCalled() @@ -474,18 +474,18 @@ describe('e2e: TransitionGroup', () => { expect(afterEnterSpy).not.toBeCalled() await nextFrame() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + `
a
` + + `
b
` + + `
c
` + + `
d
` ) expect(afterLeaveSpy).not.toBeCalled() expect(afterEnterSpy).not.toBeCalled() await transitionFinish() expect(await html('#container')).toBe( - `
b
` + - `
c
` + - `
d
` + `
b
` + + `
c
` + + `
d
` ) expect(afterLeaveSpy).toBeCalled() expect(afterEnterSpy).toBeCalled() From c44baae6a8fdd63c224007e2d3d974840248e0c8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 2 Dec 2020 14:34:34 -0500 Subject: [PATCH 4/4] refactor: do not disable transition in before enter --- .../runtime-dom/src/components/Transition.ts | 41 +++--- packages/vue/__tests__/Transition.spec.ts | 104 +++++---------- .../vue/__tests__/TransitionGroup.spec.ts | 119 +++++++++--------- 3 files changed, 104 insertions(+), 160 deletions(-) diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index 46924117b1d..49ed2d4d5f9 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -27,6 +27,14 @@ export interface TransitionProps extends BaseTransitionProps { leaveToClass?: string } +export interface ElementWithTransition extends HTMLElement { + // _vtc = Vue Transition Classes. + // Store the temporarily-added transition classes on the element + // so that we can avoid overwriting them if the element's class is patched + // during the transition. + _vtc?: Set +} + // DOM Transition is a higher-order-component based on the platform-agnostic // base Transition component, with DOM-specific logic. export const Transition: FunctionalComponent = ( @@ -123,7 +131,6 @@ export function resolveTransitionProps( const resolve = () => finishEnter(el, isAppear, done) hook && hook(el, resolve) nextFrame(() => { - enableTransition(el) removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass) addTransitionClass(el, isAppear ? appearToClass : enterToClass) if (!(hook && hook.length > 1)) { @@ -133,30 +140,16 @@ export function resolveTransitionProps( } } - // see issue #2531, #2593 - let cacheTransition: string - const disableTransition = (el: Element) => { - const style = (el as HTMLElement).style - cacheTransition = style.transition - style.transitionProperty = 'none' - } - - const enableTransition = (el: Element) => { - ;(el as HTMLElement).style.transition = cacheTransition - } - return extend(baseProps, { onBeforeEnter(el) { onBeforeEnter && onBeforeEnter(el) addTransitionClass(el, enterActiveClass) addTransitionClass(el, enterFromClass) - disableTransition(el) }, onBeforeAppear(el) { onBeforeAppear && onBeforeAppear(el) addTransitionClass(el, appearActiveClass) addTransitionClass(el, appearFromClass) - disableTransition(el) }, onEnter: makeEnterHook(false), onAppear: makeEnterHook(true), @@ -164,9 +157,15 @@ export function resolveTransitionProps( const resolve = () => finishLeave(el, done) addTransitionClass(el, leaveActiveClass) addTransitionClass(el, leaveFromClass) - disableTransition(el) + // ref #2531, #2593 + // disabling the transition before nextFrame ensures styles from + // *-leave-from and *-enter-from classes are applied instantly before + // the transition starts. This is applied for enter transition as well + // so that it accounts for `visibility: hidden` cases. + const cachedTransition = (el as HTMLElement).style.transitionProperty + ;(el as HTMLElement).style.transitionProperty = 'none' nextFrame(() => { - enableTransition(el) + ;(el as HTMLElement).style.transitionProperty = cachedTransition removeTransitionClass(el, leaveFromClass) addTransitionClass(el, leaveToClass) if (!(onLeave && onLeave.length > 1)) { @@ -223,14 +222,6 @@ function validateDuration(val: unknown) { } } -export interface ElementWithTransition extends HTMLElement { - // _vtc = Vue Transition Classes. - // Store the temporarily-added transition classes on the element - // so that we can avoid overwriting them if the element's class is patched - // during the transition. - _vtc?: Set -} - export function addTransitionClass(el: Element, cls: string) { cls.split(/\s+/).forEach(c => c && el.classList.add(c)) ;( diff --git a/packages/vue/__tests__/Transition.spec.ts b/packages/vue/__tests__/Transition.spec.ts index 2d3efcc595e..ee9b8cf6515 100644 --- a/packages/vue/__tests__/Transition.spec.ts +++ b/packages/vue/__tests__/Transition.spec.ts @@ -84,9 +84,7 @@ describe('e2e: Transition', () => { 'v-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -142,9 +140,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -205,9 +201,7 @@ describe('e2e: Transition', () => { 'hello-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -269,9 +263,7 @@ describe('e2e: Transition', () => { 'changed-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -375,9 +367,7 @@ describe('e2e: Transition', () => { ]) expect(afterEnterSpy).not.toBeCalled() await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') expect(afterEnterSpy).toBeCalled() }, E2E_TIMEOUT @@ -486,9 +476,7 @@ describe('e2e: Transition', () => { 'test-appear-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') // leave expect(await classWhenTransitionStart()).toStrictEqual([ @@ -518,9 +506,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -623,9 +609,7 @@ describe('e2e: Transition', () => { ]) expect(afterAppearSpy).not.toBeCalled() await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') expect(afterAppearSpy).toBeCalled() expect(beforeEnterSpy).not.toBeCalled() @@ -669,9 +653,7 @@ describe('e2e: Transition', () => { ]) expect(afterEnterSpy).not.toBeCalled() await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') expect(afterEnterSpy).toBeCalled() }, E2E_TIMEOUT @@ -792,9 +774,7 @@ describe('e2e: Transition', () => { 'noop-enter-from' ]) await nextFrame() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -846,9 +826,7 @@ describe('e2e: Transition', () => { 'test-anim-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -910,9 +888,7 @@ describe('e2e: Transition', () => { 'test-anim-long-enter-to' ]) await transitionFinish(duration * 2) - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -982,7 +958,7 @@ describe('e2e: Transition', () => { ]) await transitionFinish() expect(await html('#container')).toBe( - '' + '' ) }, E2E_TIMEOUT @@ -1040,9 +1016,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -1099,9 +1073,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
two
' - ) + expect(await html('#container')).toBe('
two
') // change view -> 'one' await page().evaluate(() => { @@ -1169,12 +1141,10 @@ describe('e2e: Transition', () => { expect(onEnterSpy).toBeCalledTimes(1) await nextFrame() expect(await html('#container')).toBe( - '
content
' + '
content
' ) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') // leave expect(await classWhenTransitionStart()).toStrictEqual([ @@ -1218,9 +1188,7 @@ describe('e2e: Transition', () => { 'v-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -1279,9 +1247,7 @@ describe('e2e: Transition', () => { 'v-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -1330,12 +1296,10 @@ describe('e2e: Transition', () => { await nextFrame() expect(await html('#container')).toBe( - '
one
' + '
one
' ) await transitionFinish() - expect(await html('#container')).toBe( - '
one
' - ) + expect(await html('#container')).toBe('
one
') // leave await classWhenTransitionStart() @@ -1346,12 +1310,10 @@ describe('e2e: Transition', () => { await transitionFinish() await nextFrame() expect(await html('#container')).toBe( - '
two
' + '
two
' ) await transitionFinish() - expect(await html('#container')).toBe( - '
two
' - ) + expect(await html('#container')).toBe('
two
') }, E2E_TIMEOUT ) @@ -1626,9 +1588,7 @@ describe('e2e: Transition', () => { 'test-appear-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') // leave expect(await classWhenTransitionStart()).toStrictEqual([ @@ -1735,9 +1695,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish(duration * 2) - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -1793,9 +1751,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish(duration * 2) - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -1851,9 +1807,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish() - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) @@ -1912,9 +1866,7 @@ describe('e2e: Transition', () => { 'test-enter-to' ]) await transitionFinish(200) - expect(await html('#container')).toBe( - '
content
' - ) + expect(await html('#container')).toBe('
content
') }, E2E_TIMEOUT ) diff --git a/packages/vue/__tests__/TransitionGroup.spec.ts b/packages/vue/__tests__/TransitionGroup.spec.ts index 9c82d6700c2..c3d2aa28ec4 100644 --- a/packages/vue/__tests__/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/TransitionGroup.spec.ts @@ -8,6 +8,7 @@ describe('e2e: TransitionGroup', () => { const duration = 50 const buffer = 5 + const transitionDisableProp = `style="transition-property: none;"` const htmlWhenTransitionStart = () => page().evaluate(() => { @@ -55,24 +56,24 @@ describe('e2e: TransitionGroup', () => { `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) await nextFrame() expect(await html('#container')).toBe( `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) await transitionFinish() expect(await html('#container')).toBe( `
a
` + `
b
` + `
c
` + - `
d
` + - `
e
` + `
d
` + + `
e
` ) }, E2E_TIMEOUT @@ -106,9 +107,9 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + - `
c
` + `
c
` ) await nextFrame() expect(await html('#container')).toBe( @@ -150,23 +151,23 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
a
` + + `
a
` + `
b
` + `
c
` + - `
d
` + `
d
` ) await nextFrame() expect(await html('#container')).toBe( `
a
` + `
b
` + `
c
` + - `
d
` + `
d
` ) await transitionFinish() expect(await html('#container')).toBe( `
b
` + `
c
` + - `
d
` + `
d
` ) }, E2E_TIMEOUT @@ -202,46 +203,46 @@ describe('e2e: TransitionGroup', () => { }) // appear expect(appearHtml).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await nextFrame() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await transitionFinish() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) // enter expect(await htmlWhenTransitionStart()).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + - `
e
` + `
a
` + + `
b
` + + `
c
` + + `
d
` + + `
e
` ) await nextFrame() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + - `
e
` + `
a
` + + `
b
` + + `
c
` + + `
d
` + + `
e
` ) await transitionFinish() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + - `
e
` + `
a
` + + `
b
` + + `
c
` + + `
d
` + + `
e
` ) }, E2E_TIMEOUT @@ -275,21 +276,21 @@ describe('e2e: TransitionGroup', () => { ) expect(await htmlWhenTransitionStart()).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` + - `
c
` + `
c
` ) await nextFrame() expect(await html('#container')).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` + `
c
` ) await transitionFinish(duration * 2) expect(await html('#container')).toBe( - `
d
` + + `
d
` + `
b
` + `
a
` ) @@ -440,31 +441,31 @@ describe('e2e: TransitionGroup', () => { expect(onAppearSpy).toBeCalled() expect(afterAppearSpy).not.toBeCalled() expect(appearHtml).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await nextFrame() expect(afterAppearSpy).not.toBeCalled() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) await transitionFinish() expect(afterAppearSpy).toBeCalled() expect(await html('#container')).toBe( - `
a
` + - `
b
` + - `
c
` + `
a
` + + `
b
` + + `
c
` ) // enter + leave expect(await htmlWhenTransitionStart()).toBe( - `
a
` + - `
b
` + - `
c
` + - `
d
` + `
a
` + + `
b
` + + `
c
` + + `
d
` ) expect(beforeLeaveSpy).toBeCalled() expect(onLeaveSpy).toBeCalled() @@ -475,17 +476,17 @@ describe('e2e: TransitionGroup', () => { await nextFrame() expect(await html('#container')).toBe( `
a
` + - `
b
` + - `
c
` + - `
d
` + `
b
` + + `
c
` + + `
d
` ) expect(afterLeaveSpy).not.toBeCalled() expect(afterEnterSpy).not.toBeCalled() await transitionFinish() expect(await html('#container')).toBe( - `
b
` + - `
c
` + - `
d
` + `
b
` + + `
c
` + + `
d
` ) expect(afterLeaveSpy).toBeCalled() expect(afterEnterSpy).toBeCalled()