Skip to content

Commit eaf8a67

Browse files
committed
fix(transition): avoid invoking stale transition end callbacks
fix #2482
1 parent 5ad6ed3 commit eaf8a67

File tree

1 file changed

+22
-18
lines changed

1 file changed

+22
-18
lines changed

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

+22-18
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,7 @@ export function resolveTransitionProps(
126126
removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass)
127127
addTransitionClass(el, isAppear ? appearToClass : enterToClass)
128128
if (!(hook && hook.length > 1)) {
129-
if (enterDuration) {
130-
setTimeout(resolve, enterDuration)
131-
} else {
132-
whenTransitionEnds(el, type, resolve)
133-
}
129+
whenTransitionEnds(el, type, enterDuration, resolve)
134130
}
135131
})
136132
}
@@ -157,11 +153,7 @@ export function resolveTransitionProps(
157153
removeTransitionClass(el, leaveFromClass)
158154
addTransitionClass(el, leaveToClass)
159155
if (!(onLeave && onLeave.length > 1)) {
160-
if (leaveDuration) {
161-
setTimeout(resolve, leaveDuration)
162-
} else {
163-
whenTransitionEnds(el, type, resolve)
164-
}
156+
whenTransitionEnds(el, type, leaveDuration, resolve)
165157
}
166158
})
167159
onLeave && onLeave(el, resolve)
@@ -247,27 +239,39 @@ function nextFrame(cb: () => void) {
247239
})
248240
}
249241

242+
let endId = 0
243+
250244
function whenTransitionEnds(
251-
el: Element,
245+
el: Element & { _endId?: number },
252246
expectedType: TransitionProps['type'] | undefined,
253-
cb: () => void
247+
explicitTimeout: number | null,
248+
resolve: () => void
254249
) {
250+
const id = (el._endId = ++endId)
251+
const resolveIfNotStale = () => {
252+
if (id === el._endId) {
253+
resolve()
254+
}
255+
}
256+
257+
if (explicitTimeout) {
258+
return setTimeout(resolveIfNotStale, explicitTimeout)
259+
}
260+
255261
const { type, timeout, propCount } = getTransitionInfo(el, expectedType)
256262
if (!type) {
257-
return cb()
263+
return resolve()
258264
}
259265

260266
const endEvent = type + 'end'
261267
let ended = 0
262268
const end = () => {
263269
el.removeEventListener(endEvent, onEnd)
264-
cb()
270+
resolveIfNotStale()
265271
}
266272
const onEnd = (e: Event) => {
267-
if (e.target === el) {
268-
if (++ended >= propCount) {
269-
end()
270-
}
273+
if (e.target === el && ++ended >= propCount) {
274+
end()
271275
}
272276
}
273277
setTimeout(() => {

0 commit comments

Comments
 (0)