Skip to content

Commit

Permalink
refactor: do not disable transition in before enter
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 2, 2020
1 parent 3b4198e commit c44baae
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 160 deletions.
41 changes: 16 additions & 25 deletions packages/runtime-dom/src/components/Transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export interface TransitionProps extends BaseTransitionProps<Element> {
leaveToClass?: string
}

export interface ElementWithTransition extends HTMLElement {
// _vtc = Vue Transition Classes.
// Store the temporarily-added transition classes on the element
// so that we can avoid overwriting them if the element's class is patched
// during the transition.
_vtc?: Set<string>
}

// DOM Transition is a higher-order-component based on the platform-agnostic
// base Transition component, with DOM-specific logic.
export const Transition: FunctionalComponent<TransitionProps> = (
Expand Down Expand Up @@ -123,7 +131,6 @@ export function resolveTransitionProps(
const resolve = () => finishEnter(el, isAppear, done)
hook && hook(el, resolve)
nextFrame(() => {
enableTransition(el)
removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass)
addTransitionClass(el, isAppear ? appearToClass : enterToClass)
if (!(hook && hook.length > 1)) {
Expand All @@ -133,40 +140,32 @@ export function resolveTransitionProps(
}
}

// see issue #2531, #2593
let cacheTransition: string
const disableTransition = (el: Element) => {
const style = (el as HTMLElement).style
cacheTransition = style.transition
style.transitionProperty = 'none'
}

const enableTransition = (el: Element) => {
;(el as HTMLElement).style.transition = cacheTransition
}

return extend(baseProps, {
onBeforeEnter(el) {
onBeforeEnter && onBeforeEnter(el)
addTransitionClass(el, enterActiveClass)
addTransitionClass(el, enterFromClass)
disableTransition(el)
},
onBeforeAppear(el) {
onBeforeAppear && onBeforeAppear(el)
addTransitionClass(el, appearActiveClass)
addTransitionClass(el, appearFromClass)
disableTransition(el)
},
onEnter: makeEnterHook(false),
onAppear: makeEnterHook(true),
onLeave(el, done) {
const resolve = () => finishLeave(el, done)
addTransitionClass(el, leaveActiveClass)
addTransitionClass(el, leaveFromClass)
disableTransition(el)
// ref #2531, #2593
// disabling the transition before nextFrame ensures styles from
// *-leave-from and *-enter-from classes are applied instantly before
// the transition starts. This is applied for enter transition as well
// so that it accounts for `visibility: hidden` cases.
const cachedTransition = (el as HTMLElement).style.transitionProperty
;(el as HTMLElement).style.transitionProperty = 'none'
nextFrame(() => {
enableTransition(el)
;(el as HTMLElement).style.transitionProperty = cachedTransition
removeTransitionClass(el, leaveFromClass)
addTransitionClass(el, leaveToClass)
if (!(onLeave && onLeave.length > 1)) {
Expand Down Expand Up @@ -223,14 +222,6 @@ function validateDuration(val: unknown) {
}
}

export interface ElementWithTransition extends HTMLElement {
// _vtc = Vue Transition Classes.
// Store the temporarily-added transition classes on the element
// so that we can avoid overwriting them if the element's class is patched
// during the transition.
_vtc?: Set<string>
}

export function addTransitionClass(el: Element, cls: string) {
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
;(
Expand Down
104 changes: 28 additions & 76 deletions packages/vue/__tests__/Transition.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ describe('e2e: Transition', () => {
'v-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -142,9 +140,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -205,9 +201,7 @@ describe('e2e: Transition', () => {
'hello-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -269,9 +263,7 @@ describe('e2e: Transition', () => {
'changed-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -375,9 +367,7 @@ describe('e2e: Transition', () => {
])
expect(afterEnterSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
expect(afterEnterSpy).toBeCalled()
},
E2E_TIMEOUT
Expand Down Expand Up @@ -486,9 +476,7 @@ describe('e2e: Transition', () => {
'test-appear-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')

// leave
expect(await classWhenTransitionStart()).toStrictEqual([
Expand Down Expand Up @@ -518,9 +506,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -623,9 +609,7 @@ describe('e2e: Transition', () => {
])
expect(afterAppearSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
expect(afterAppearSpy).toBeCalled()

expect(beforeEnterSpy).not.toBeCalled()
Expand Down Expand Up @@ -669,9 +653,7 @@ describe('e2e: Transition', () => {
])
expect(afterEnterSpy).not.toBeCalled()
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
expect(afterEnterSpy).toBeCalled()
},
E2E_TIMEOUT
Expand Down Expand Up @@ -792,9 +774,7 @@ describe('e2e: Transition', () => {
'noop-enter-from'
])
await nextFrame()
expect(await html('#container')).toBe(
'<div class="" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -846,9 +826,7 @@ describe('e2e: Transition', () => {
'test-anim-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -910,9 +888,7 @@ describe('e2e: Transition', () => {
'test-anim-long-enter-to'
])
await transitionFinish(duration * 2)
expect(await html('#container')).toBe(
'<div class="" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -982,7 +958,7 @@ describe('e2e: Transition', () => {
])
await transitionFinish()
expect(await html('#container')).toBe(
'<circle cx="0" cy="0" r="10" class="test" style=""></circle>'
'<circle cx="0" cy="0" r="10" class="test"></circle>'
)
},
E2E_TIMEOUT
Expand Down Expand Up @@ -1040,9 +1016,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1099,9 +1073,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">two</div>'
)
expect(await html('#container')).toBe('<div class="test">two</div>')

// change view -> 'one'
await page().evaluate(() => {
Expand Down Expand Up @@ -1169,12 +1141,10 @@ describe('e2e: Transition', () => {
expect(onEnterSpy).toBeCalledTimes(1)
await nextFrame()
expect(await html('#container')).toBe(
'<div class="test v-enter-active v-enter-to" style="">content</div>'
'<div class="test v-enter-active v-enter-to">content</div>'
)
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')

// leave
expect(await classWhenTransitionStart()).toStrictEqual([
Expand Down Expand Up @@ -1218,9 +1188,7 @@ describe('e2e: Transition', () => {
'v-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1279,9 +1247,7 @@ describe('e2e: Transition', () => {
'v-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1330,12 +1296,10 @@ describe('e2e: Transition', () => {

await nextFrame()
expect(await html('#container')).toBe(
'<div class="test v-enter-active v-enter-to" style="">one</div>'
'<div class="test v-enter-active v-enter-to">one</div>'
)
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">one</div>'
)
expect(await html('#container')).toBe('<div class="test">one</div>')

// leave
await classWhenTransitionStart()
Expand All @@ -1346,12 +1310,10 @@ describe('e2e: Transition', () => {
await transitionFinish()
await nextFrame()
expect(await html('#container')).toBe(
'<div class="test v-enter-active v-enter-to" style="">two</div>'
'<div class="test v-enter-active v-enter-to">two</div>'
)
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">two</div>'
)
expect(await html('#container')).toBe('<div class="test">two</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1626,9 +1588,7 @@ describe('e2e: Transition', () => {
'test-appear-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')

// leave
expect(await classWhenTransitionStart()).toStrictEqual([
Expand Down Expand Up @@ -1735,9 +1695,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish(duration * 2)
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1793,9 +1751,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish(duration * 2)
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1851,9 +1807,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish()
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down Expand Up @@ -1912,9 +1866,7 @@ describe('e2e: Transition', () => {
'test-enter-to'
])
await transitionFinish(200)
expect(await html('#container')).toBe(
'<div class="test" style="">content</div>'
)
expect(await html('#container')).toBe('<div class="test">content</div>')
},
E2E_TIMEOUT
)
Expand Down
Loading

0 comments on commit c44baae

Please sign in to comment.