Skip to content

Commit e2618a6

Browse files
authored
fix(transition): respect rules in *-leave-from transition class (#2597)
fix #2593
1 parent 20a704f commit e2618a6

File tree

3 files changed

+28
-18
lines changed

3 files changed

+28
-18
lines changed

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

+16-8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ export interface TransitionProps extends BaseTransitionProps<Element> {
2727
leaveToClass?: string
2828
}
2929

30+
export interface ElementWithTransition extends HTMLElement {
31+
// _vtc = Vue Transition Classes.
32+
// Store the temporarily-added transition classes on the element
33+
// so that we can avoid overwriting them if the element's class is patched
34+
// during the transition.
35+
_vtc?: Set<string>
36+
}
37+
3038
// DOM Transition is a higher-order-component based on the platform-agnostic
3139
// base Transition component, with DOM-specific logic.
3240
export const Transition: FunctionalComponent<TransitionProps> = (
@@ -149,7 +157,15 @@ export function resolveTransitionProps(
149157
const resolve = () => finishLeave(el, done)
150158
addTransitionClass(el, leaveActiveClass)
151159
addTransitionClass(el, leaveFromClass)
160+
// ref #2531, #2593
161+
// disabling the transition before nextFrame ensures styles from
162+
// *-leave-from and *-enter-from classes are applied instantly before
163+
// the transition starts. This is applied for enter transition as well
164+
// so that it accounts for `visibility: hidden` cases.
165+
const cachedTransition = (el as HTMLElement).style.transitionProperty
166+
;(el as HTMLElement).style.transitionProperty = 'none'
152167
nextFrame(() => {
168+
;(el as HTMLElement).style.transitionProperty = cachedTransition
153169
removeTransitionClass(el, leaveFromClass)
154170
addTransitionClass(el, leaveToClass)
155171
if (!(onLeave && onLeave.length > 1)) {
@@ -206,14 +222,6 @@ function validateDuration(val: unknown) {
206222
}
207223
}
208224

209-
export interface ElementWithTransition extends HTMLElement {
210-
// _vtc = Vue Transition Classes.
211-
// Store the temporarily-added transition classes on the element
212-
// so that we can avoid overwriting them if the element's class is patched
213-
// during the transition.
214-
_vtc?: Set<string>
215-
}
216-
217225
export function addTransitionClass(el: Element, cls: string) {
218226
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
219227
;(

packages/vue/__tests__/Transition.spec.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1305,9 +1305,10 @@ describe('e2e: Transition', () => {
13051305
await classWhenTransitionStart()
13061306
await nextFrame()
13071307
expect(await html('#container')).toBe(
1308-
'<div class="test v-leave-active v-leave-to">one</div>'
1308+
'<div class="test v-leave-active v-leave-to" style="">one</div>'
13091309
)
13101310
await transitionFinish()
1311+
await nextFrame()
13111312
expect(await html('#container')).toBe(
13121313
'<div class="test v-enter-active v-enter-to">two</div>'
13131314
)

packages/vue/__tests__/TransitionGroup.spec.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ describe('e2e: TransitionGroup', () => {
88

99
const duration = 50
1010
const buffer = 5
11+
const transitionDisableProp = `style="transition-property: none;"`
1112

1213
const htmlWhenTransitionStart = () =>
1314
page().evaluate(() => {
@@ -106,15 +107,15 @@ describe('e2e: TransitionGroup', () => {
106107
)
107108

108109
expect(await htmlWhenTransitionStart()).toBe(
109-
`<div class="test test-leave-active test-leave-from">a</div>` +
110+
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>a</div>` +
110111
`<div class="test">b</div>` +
111-
`<div class="test test-leave-active test-leave-from">c</div>`
112+
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>c</div>`
112113
)
113114
await nextFrame()
114115
expect(await html('#container')).toBe(
115-
`<div class="test test-leave-active test-leave-to">a</div>` +
116+
`<div class="test test-leave-active test-leave-to" style="">a</div>` +
116117
`<div class="test">b</div>` +
117-
`<div class="test test-leave-active test-leave-to">c</div>`
118+
`<div class="test test-leave-active test-leave-to" style="">c</div>`
118119
)
119120
await transitionFinish()
120121
expect(await html('#container')).toBe(`<div class="test">b</div>`)
@@ -150,14 +151,14 @@ describe('e2e: TransitionGroup', () => {
150151
)
151152

152153
expect(await htmlWhenTransitionStart()).toBe(
153-
`<div class="test test-leave-active test-leave-from">a</div>` +
154+
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>a</div>` +
154155
`<div class="test">b</div>` +
155156
`<div class="test">c</div>` +
156157
`<div class="test test-enter-active test-enter-from">d</div>`
157158
)
158159
await nextFrame()
159160
expect(await html('#container')).toBe(
160-
`<div class="test test-leave-active test-leave-to">a</div>` +
161+
`<div class="test test-leave-active test-leave-to" style="">a</div>` +
161162
`<div class="test">b</div>` +
162163
`<div class="test">c</div>` +
163164
`<div class="test test-enter-active test-enter-to">d</div>`
@@ -278,7 +279,7 @@ describe('e2e: TransitionGroup', () => {
278279
`<div class="test group-enter-active group-enter-from">d</div>` +
279280
`<div class="test">b</div>` +
280281
`<div class="test group-move" style="">a</div>` +
281-
`<div class="test group-leave-active group-leave-from group-move" style="">c</div>`
282+
`<div class="test group-leave-active group-leave-from group-move" ${transitionDisableProp}>c</div>`
282283
)
283284
await nextFrame()
284285
expect(await html('#container')).toBe(
@@ -461,7 +462,7 @@ describe('e2e: TransitionGroup', () => {
461462

462463
// enter + leave
463464
expect(await htmlWhenTransitionStart()).toBe(
464-
`<div class="test test-leave-active test-leave-from">a</div>` +
465+
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>a</div>` +
465466
`<div class="test">b</div>` +
466467
`<div class="test">c</div>` +
467468
`<div class="test test-enter-active test-enter-from">d</div>`
@@ -474,7 +475,7 @@ describe('e2e: TransitionGroup', () => {
474475
expect(afterEnterSpy).not.toBeCalled()
475476
await nextFrame()
476477
expect(await html('#container')).toBe(
477-
`<div class="test test-leave-active test-leave-to">a</div>` +
478+
`<div class="test test-leave-active test-leave-to" style="">a</div>` +
478479
`<div class="test">b</div>` +
479480
`<div class="test">c</div>` +
480481
`<div class="test test-enter-active test-enter-to">d</div>`

0 commit comments

Comments
 (0)