Skip to content

Commit

Permalink
fix(transition): reflow before leave-active class after leave-from (#…
Browse files Browse the repository at this point in the history
…12288)

re-fix #2593
  • Loading branch information
Tadehz authored Nov 15, 2024
1 parent a20a4cb commit 4b479db
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 8 deletions.
28 changes: 21 additions & 7 deletions packages/runtime-dom/src/components/Transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,13 @@ export function resolveTransitionProps(
onAppearCancelled = onEnterCancelled,
} = baseProps

const finishEnter = (el: Element, isAppear: boolean, done?: () => void) => {
const finishEnter = (
el: Element & { _enterCancelled?: boolean },
isAppear: boolean,
done?: () => void,
isCancelled?: boolean,
) => {
el._enterCancelled = isCancelled
removeTransitionClass(el, isAppear ? appearToClass : enterToClass)
removeTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass)
done && done()
Expand Down Expand Up @@ -240,7 +246,10 @@ export function resolveTransitionProps(
},
onEnter: makeEnterHook(false),
onAppear: makeEnterHook(true),
onLeave(el: Element & { _isLeaving?: boolean }, done) {
onLeave(
el: Element & { _isLeaving?: boolean; _enterCancelled?: boolean },
done,
) {
el._isLeaving = true
const resolve = () => finishLeave(el, done)
addTransitionClass(el, leaveFromClass)
Expand All @@ -249,9 +258,14 @@ export function resolveTransitionProps(
}
// add *-leave-active class before reflow so in the case of a cancelled enter transition
// the css will not get the final state (#10677)
addTransitionClass(el, leaveActiveClass)
// force reflow so *-leave-from classes immediately take effect (#2593)
forceReflow()
if (!el._enterCancelled) {
// force reflow so *-leave-from classes immediately take effect (#2593)
forceReflow()
addTransitionClass(el, leaveActiveClass)
} else {
addTransitionClass(el, leaveActiveClass)
forceReflow()
}
nextFrame(() => {
if (!el._isLeaving) {
// cancelled
Expand All @@ -269,11 +283,11 @@ export function resolveTransitionProps(
callHook(onLeave, [el, resolve])
},
onEnterCancelled(el) {
finishEnter(el, false)
finishEnter(el, false, undefined, true)
callHook(onEnterCancelled, [el])
},
onAppearCancelled(el) {
finishEnter(el, true)
finishEnter(el, true, undefined, true)
callHook(onAppearCancelled, [el])
},
onLeaveCancelled(el) {
Expand Down
51 changes: 50 additions & 1 deletion packages/vue/__tests__/e2e/Transition.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path'
import { Transition, createApp, h, nextTick, ref } from 'vue'

describe('e2e: Transition', () => {
const { page, html, classList, isVisible, timeout, nextFrame, click } =
const { page, html, classList, style, isVisible, timeout, nextFrame, click } =
setupPuppeteer()
const baseUrl = `file://${path.resolve(__dirname, './transition.html')}`

Expand Down Expand Up @@ -2986,6 +2986,55 @@ describe('e2e: Transition', () => {
)
})

test('reflow after *-leave-from before *-leave-active', async () => {
await page().evaluate(() => {
const { createApp, ref } = (window as any).Vue
createApp({
template: `
<div id="container">
<transition name="test-reflow">
<div v-if="toggle" class="test-reflow">content</div>
</transition>
</div>
<button id="toggleBtn" @click="click">button</button>
`,
setup: () => {
const toggle = ref(false)
const click = () => (toggle.value = !toggle.value)
return {
toggle,
click,
}
},
}).mount('#app')
})

// if transition starts while there's v-leave-active added along with v-leave-from, its bad, it has to start when it doesnt have the v-leave-from

// enter
await classWhenTransitionStart()
await transitionFinish()

// leave
expect(await classWhenTransitionStart()).toStrictEqual([
'test-reflow',
'test-reflow-leave-from',
'test-reflow-leave-active',
])

expect(await style('.test-reflow', 'opacity')).toStrictEqual('0.9')

await nextFrame()
expect(await classList('.test-reflow')).toStrictEqual([
'test-reflow',
'test-reflow-leave-active',
'test-reflow-leave-to',
])

await transitionFinish()
expect(await html('#container')).toBe('<!--v-if-->')
})

test('warn when used on multiple elements', async () => {
createApp({
render() {
Expand Down
15 changes: 15 additions & 0 deletions packages/vue/__tests__/e2e/e2eUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ interface PuppeteerUtils {
value(selector: string): Promise<string>
html(selector: string): Promise<string>
classList(selector: string): Promise<string[]>
style(selector: string, property: keyof CSSStyleDeclaration): Promise<any>
children(selector: string): Promise<any[]>
isVisible(selector: string): Promise<boolean>
isChecked(selector: string): Promise<boolean>
Expand Down Expand Up @@ -120,6 +121,19 @@ export function setupPuppeteer(args?: string[]): PuppeteerUtils {
return page.$eval(selector, (node: any) => [...node.children])
}

async function style(
selector: string,
property: keyof CSSStyleDeclaration,
): Promise<any> {
return await page.$eval(
selector,
(node, property) => {
return window.getComputedStyle(node)[property]
},
property,
)
}

async function isVisible(selector: string): Promise<boolean> {
const display = await page.$eval(selector, node => {
return window.getComputedStyle(node).display
Expand Down Expand Up @@ -195,6 +209,7 @@ export function setupPuppeteer(args?: string[]): PuppeteerUtils {
value,
html,
classList,
style,
children,
isVisible,
isChecked,
Expand Down
10 changes: 10 additions & 0 deletions packages/vue/__tests__/e2e/transition.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@
.test-appear,
.test-enter,
.test-leave-active,
.test-reflow-enter,
.test-reflow-leave-to,
.hello,
.bye.active,
.changed-enter {
opacity: 0;
}
.test-reflow-leave-active,
.test-reflow-enter-active {
-webkit-transition: opacity 50ms ease;
transition: opacity 50ms ease;
}
.test-reflow-leave-from {
opacity: 0.9;
}
.test-anim-enter-active {
animation: test-enter 50ms;
-webkit-animation: test-enter 50ms;
Expand Down

0 comments on commit 4b479db

Please sign in to comment.