Skip to content

Commit ddbe53b

Browse files
committed
proper transition start detection (fix #2452)
1 parent e211c88 commit ddbe53b

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

src/transition/transition.js

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,36 @@ import {
1010
animationEndEvent,
1111
transitionProp,
1212
animationProp,
13-
warn
13+
warn,
14+
inBrowser
1415
} from '../util/index'
1516

1617
const TYPE_TRANSITION = 'transition'
1718
const TYPE_ANIMATION = 'animation'
1819
const transDurationProp = transitionProp + 'Duration'
1920
const animDurationProp = animationProp + 'Duration'
2021

22+
/**
23+
* If a just-entered element is applied the
24+
* leave class while its enter transition hasn't started yet,
25+
* and the transitioned property has the same value for both
26+
* enter/leave, then the leave transition will be skipped and
27+
* the transitionend event never fires. This function ensures
28+
* its callback to be called after a transition has started
29+
* by waiting for double raf.
30+
*
31+
* It falls back to setTimeout on devices that support CSS
32+
* transitions but not raf (e.g. Android 4.2 browser) - since
33+
* these environments are usually slow, we are giving it a
34+
* relatively large timeout.
35+
*/
36+
37+
const raf = inBrowser && window.requestAnimationFrame
38+
const waitForTransitionStart = raf
39+
/* istanbul ignore next */
40+
? function (fn) { raf(function () { raf(fn) }) }
41+
: function (fn) { setTimeout(fn, 50) }
42+
2143
/**
2244
* A Transition object that encapsulates the state and logic
2345
* of the transition.
@@ -117,19 +139,11 @@ p.enter = function (op, cb) {
117139
*/
118140

119141
p.enterNextTick = function () {
120-
// Important hack:
121-
// in Chrome, if a just-entered element is applied the
122-
// leave class while its interpolated property still has
123-
// a very small value (within one frame), Chrome will
124-
// skip the leave transition entirely and not firing the
125-
// transtionend event. Therefore we need to protected
126-
// against such cases using a one-frame timeout.
142+
// prevent transition skipping
127143
this.justEntered = true
128-
var self = this
129-
setTimeout(function () {
130-
self.justEntered = false
131-
}, 17)
132-
144+
waitForTransitionStart(() => {
145+
this.justEntered = false
146+
})
133147
var enterDone = this.enterDone
134148
var type = this.getCssTransitionType(this.enterClass)
135149
if (!this.pendingJsCb) {

test/unit/specs/transition/transition_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ if (!_.isIE9) {
194194
expect(el.classList.contains('test-no-trans-leave')).toBe(false)
195195
done()
196196
})
197-
}, 17)
197+
}, 50)
198198
})
199199
})
200200

0 commit comments

Comments
 (0)