Skip to content

Commit c44baae

Browse files
committed
refactor: do not disable transition in before enter
1 parent 3b4198e commit c44baae

File tree

3 files changed

+104
-160
lines changed

3 files changed

+104
-160
lines changed

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

+16-25
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> = (
@@ -123,7 +131,6 @@ export function resolveTransitionProps(
123131
const resolve = () => finishEnter(el, isAppear, done)
124132
hook && hook(el, resolve)
125133
nextFrame(() => {
126-
enableTransition(el)
127134
removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass)
128135
addTransitionClass(el, isAppear ? appearToClass : enterToClass)
129136
if (!(hook && hook.length > 1)) {
@@ -133,40 +140,32 @@ export function resolveTransitionProps(
133140
}
134141
}
135142

136-
// see issue #2531, #2593
137-
let cacheTransition: string
138-
const disableTransition = (el: Element) => {
139-
const style = (el as HTMLElement).style
140-
cacheTransition = style.transition
141-
style.transitionProperty = 'none'
142-
}
143-
144-
const enableTransition = (el: Element) => {
145-
;(el as HTMLElement).style.transition = cacheTransition
146-
}
147-
148143
return extend(baseProps, {
149144
onBeforeEnter(el) {
150145
onBeforeEnter && onBeforeEnter(el)
151146
addTransitionClass(el, enterActiveClass)
152147
addTransitionClass(el, enterFromClass)
153-
disableTransition(el)
154148
},
155149
onBeforeAppear(el) {
156150
onBeforeAppear && onBeforeAppear(el)
157151
addTransitionClass(el, appearActiveClass)
158152
addTransitionClass(el, appearFromClass)
159-
disableTransition(el)
160153
},
161154
onEnter: makeEnterHook(false),
162155
onAppear: makeEnterHook(true),
163156
onLeave(el, done) {
164157
const resolve = () => finishLeave(el, done)
165158
addTransitionClass(el, leaveActiveClass)
166159
addTransitionClass(el, leaveFromClass)
167-
disableTransition(el)
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'
168167
nextFrame(() => {
169-
enableTransition(el)
168+
;(el as HTMLElement).style.transitionProperty = cachedTransition
170169
removeTransitionClass(el, leaveFromClass)
171170
addTransitionClass(el, leaveToClass)
172171
if (!(onLeave && onLeave.length > 1)) {
@@ -223,14 +222,6 @@ function validateDuration(val: unknown) {
223222
}
224223
}
225224

226-
export interface ElementWithTransition extends HTMLElement {
227-
// _vtc = Vue Transition Classes.
228-
// Store the temporarily-added transition classes on the element
229-
// so that we can avoid overwriting them if the element's class is patched
230-
// during the transition.
231-
_vtc?: Set<string>
232-
}
233-
234225
export function addTransitionClass(el: Element, cls: string) {
235226
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
236227
;(

packages/vue/__tests__/Transition.spec.ts

+28-76
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,7 @@ describe('e2e: Transition', () => {
8484
'v-enter-to'
8585
])
8686
await transitionFinish()
87-
expect(await html('#container')).toBe(
88-
'<div class="test" style="">content</div>'
89-
)
87+
expect(await html('#container')).toBe('<div class="test">content</div>')
9088
},
9189
E2E_TIMEOUT
9290
)
@@ -142,9 +140,7 @@ describe('e2e: Transition', () => {
142140
'test-enter-to'
143141
])
144142
await transitionFinish()
145-
expect(await html('#container')).toBe(
146-
'<div class="test" style="">content</div>'
147-
)
143+
expect(await html('#container')).toBe('<div class="test">content</div>')
148144
},
149145
E2E_TIMEOUT
150146
)
@@ -205,9 +201,7 @@ describe('e2e: Transition', () => {
205201
'hello-to'
206202
])
207203
await transitionFinish()
208-
expect(await html('#container')).toBe(
209-
'<div class="test" style="">content</div>'
210-
)
204+
expect(await html('#container')).toBe('<div class="test">content</div>')
211205
},
212206
E2E_TIMEOUT
213207
)
@@ -269,9 +263,7 @@ describe('e2e: Transition', () => {
269263
'changed-enter-to'
270264
])
271265
await transitionFinish()
272-
expect(await html('#container')).toBe(
273-
'<div class="test" style="">content</div>'
274-
)
266+
expect(await html('#container')).toBe('<div class="test">content</div>')
275267
},
276268
E2E_TIMEOUT
277269
)
@@ -375,9 +367,7 @@ describe('e2e: Transition', () => {
375367
])
376368
expect(afterEnterSpy).not.toBeCalled()
377369
await transitionFinish()
378-
expect(await html('#container')).toBe(
379-
'<div class="test" style="">content</div>'
380-
)
370+
expect(await html('#container')).toBe('<div class="test">content</div>')
381371
expect(afterEnterSpy).toBeCalled()
382372
},
383373
E2E_TIMEOUT
@@ -486,9 +476,7 @@ describe('e2e: Transition', () => {
486476
'test-appear-to'
487477
])
488478
await transitionFinish()
489-
expect(await html('#container')).toBe(
490-
'<div class="test" style="">content</div>'
491-
)
479+
expect(await html('#container')).toBe('<div class="test">content</div>')
492480

493481
// leave
494482
expect(await classWhenTransitionStart()).toStrictEqual([
@@ -518,9 +506,7 @@ describe('e2e: Transition', () => {
518506
'test-enter-to'
519507
])
520508
await transitionFinish()
521-
expect(await html('#container')).toBe(
522-
'<div class="test" style="">content</div>'
523-
)
509+
expect(await html('#container')).toBe('<div class="test">content</div>')
524510
},
525511
E2E_TIMEOUT
526512
)
@@ -623,9 +609,7 @@ describe('e2e: Transition', () => {
623609
])
624610
expect(afterAppearSpy).not.toBeCalled()
625611
await transitionFinish()
626-
expect(await html('#container')).toBe(
627-
'<div class="test" style="">content</div>'
628-
)
612+
expect(await html('#container')).toBe('<div class="test">content</div>')
629613
expect(afterAppearSpy).toBeCalled()
630614

631615
expect(beforeEnterSpy).not.toBeCalled()
@@ -669,9 +653,7 @@ describe('e2e: Transition', () => {
669653
])
670654
expect(afterEnterSpy).not.toBeCalled()
671655
await transitionFinish()
672-
expect(await html('#container')).toBe(
673-
'<div class="test" style="">content</div>'
674-
)
656+
expect(await html('#container')).toBe('<div class="test">content</div>')
675657
expect(afterEnterSpy).toBeCalled()
676658
},
677659
E2E_TIMEOUT
@@ -792,9 +774,7 @@ describe('e2e: Transition', () => {
792774
'noop-enter-from'
793775
])
794776
await nextFrame()
795-
expect(await html('#container')).toBe(
796-
'<div class="" style="">content</div>'
797-
)
777+
expect(await html('#container')).toBe('<div class="">content</div>')
798778
},
799779
E2E_TIMEOUT
800780
)
@@ -846,9 +826,7 @@ describe('e2e: Transition', () => {
846826
'test-anim-enter-to'
847827
])
848828
await transitionFinish()
849-
expect(await html('#container')).toBe(
850-
'<div class="" style="">content</div>'
851-
)
829+
expect(await html('#container')).toBe('<div class="">content</div>')
852830
},
853831
E2E_TIMEOUT
854832
)
@@ -910,9 +888,7 @@ describe('e2e: Transition', () => {
910888
'test-anim-long-enter-to'
911889
])
912890
await transitionFinish(duration * 2)
913-
expect(await html('#container')).toBe(
914-
'<div class="" style="">content</div>'
915-
)
891+
expect(await html('#container')).toBe('<div class="">content</div>')
916892
},
917893
E2E_TIMEOUT
918894
)
@@ -982,7 +958,7 @@ describe('e2e: Transition', () => {
982958
])
983959
await transitionFinish()
984960
expect(await html('#container')).toBe(
985-
'<circle cx="0" cy="0" r="10" class="test" style=""></circle>'
961+
'<circle cx="0" cy="0" r="10" class="test"></circle>'
986962
)
987963
},
988964
E2E_TIMEOUT
@@ -1040,9 +1016,7 @@ describe('e2e: Transition', () => {
10401016
'test-enter-to'
10411017
])
10421018
await transitionFinish()
1043-
expect(await html('#container')).toBe(
1044-
'<div class="test" style="">content</div>'
1045-
)
1019+
expect(await html('#container')).toBe('<div class="test">content</div>')
10461020
},
10471021
E2E_TIMEOUT
10481022
)
@@ -1099,9 +1073,7 @@ describe('e2e: Transition', () => {
10991073
'test-enter-to'
11001074
])
11011075
await transitionFinish()
1102-
expect(await html('#container')).toBe(
1103-
'<div class="test" style="">two</div>'
1104-
)
1076+
expect(await html('#container')).toBe('<div class="test">two</div>')
11051077

11061078
// change view -> 'one'
11071079
await page().evaluate(() => {
@@ -1169,12 +1141,10 @@ describe('e2e: Transition', () => {
11691141
expect(onEnterSpy).toBeCalledTimes(1)
11701142
await nextFrame()
11711143
expect(await html('#container')).toBe(
1172-
'<div class="test v-enter-active v-enter-to" style="">content</div>'
1144+
'<div class="test v-enter-active v-enter-to">content</div>'
11731145
)
11741146
await transitionFinish()
1175-
expect(await html('#container')).toBe(
1176-
'<div class="test" style="">content</div>'
1177-
)
1147+
expect(await html('#container')).toBe('<div class="test">content</div>')
11781148

11791149
// leave
11801150
expect(await classWhenTransitionStart()).toStrictEqual([
@@ -1218,9 +1188,7 @@ describe('e2e: Transition', () => {
12181188
'v-enter-to'
12191189
])
12201190
await transitionFinish()
1221-
expect(await html('#container')).toBe(
1222-
'<div class="test" style="">content</div>'
1223-
)
1191+
expect(await html('#container')).toBe('<div class="test">content</div>')
12241192
},
12251193
E2E_TIMEOUT
12261194
)
@@ -1279,9 +1247,7 @@ describe('e2e: Transition', () => {
12791247
'v-enter-to'
12801248
])
12811249
await transitionFinish()
1282-
expect(await html('#container')).toBe(
1283-
'<div class="test" style="">content</div>'
1284-
)
1250+
expect(await html('#container')).toBe('<div class="test">content</div>')
12851251
},
12861252
E2E_TIMEOUT
12871253
)
@@ -1330,12 +1296,10 @@ describe('e2e: Transition', () => {
13301296

13311297
await nextFrame()
13321298
expect(await html('#container')).toBe(
1333-
'<div class="test v-enter-active v-enter-to" style="">one</div>'
1299+
'<div class="test v-enter-active v-enter-to">one</div>'
13341300
)
13351301
await transitionFinish()
1336-
expect(await html('#container')).toBe(
1337-
'<div class="test" style="">one</div>'
1338-
)
1302+
expect(await html('#container')).toBe('<div class="test">one</div>')
13391303

13401304
// leave
13411305
await classWhenTransitionStart()
@@ -1346,12 +1310,10 @@ describe('e2e: Transition', () => {
13461310
await transitionFinish()
13471311
await nextFrame()
13481312
expect(await html('#container')).toBe(
1349-
'<div class="test v-enter-active v-enter-to" style="">two</div>'
1313+
'<div class="test v-enter-active v-enter-to">two</div>'
13501314
)
13511315
await transitionFinish()
1352-
expect(await html('#container')).toBe(
1353-
'<div class="test" style="">two</div>'
1354-
)
1316+
expect(await html('#container')).toBe('<div class="test">two</div>')
13551317
},
13561318
E2E_TIMEOUT
13571319
)
@@ -1626,9 +1588,7 @@ describe('e2e: Transition', () => {
16261588
'test-appear-to'
16271589
])
16281590
await transitionFinish()
1629-
expect(await html('#container')).toBe(
1630-
'<div class="test" style="">content</div>'
1631-
)
1591+
expect(await html('#container')).toBe('<div class="test">content</div>')
16321592

16331593
// leave
16341594
expect(await classWhenTransitionStart()).toStrictEqual([
@@ -1735,9 +1695,7 @@ describe('e2e: Transition', () => {
17351695
'test-enter-to'
17361696
])
17371697
await transitionFinish(duration * 2)
1738-
expect(await html('#container')).toBe(
1739-
'<div class="test" style="">content</div>'
1740-
)
1698+
expect(await html('#container')).toBe('<div class="test">content</div>')
17411699
},
17421700
E2E_TIMEOUT
17431701
)
@@ -1793,9 +1751,7 @@ describe('e2e: Transition', () => {
17931751
'test-enter-to'
17941752
])
17951753
await transitionFinish(duration * 2)
1796-
expect(await html('#container')).toBe(
1797-
'<div class="test" style="">content</div>'
1798-
)
1754+
expect(await html('#container')).toBe('<div class="test">content</div>')
17991755
},
18001756
E2E_TIMEOUT
18011757
)
@@ -1851,9 +1807,7 @@ describe('e2e: Transition', () => {
18511807
'test-enter-to'
18521808
])
18531809
await transitionFinish()
1854-
expect(await html('#container')).toBe(
1855-
'<div class="test" style="">content</div>'
1856-
)
1810+
expect(await html('#container')).toBe('<div class="test">content</div>')
18571811
},
18581812
E2E_TIMEOUT
18591813
)
@@ -1912,9 +1866,7 @@ describe('e2e: Transition', () => {
19121866
'test-enter-to'
19131867
])
19141868
await transitionFinish(200)
1915-
expect(await html('#container')).toBe(
1916-
'<div class="test" style="">content</div>'
1917-
)
1869+
expect(await html('#container')).toBe('<div class="test">content</div>')
19181870
},
19191871
E2E_TIMEOUT
19201872
)

0 commit comments

Comments
 (0)