E2E_TIMEOUT,
)
- test.todo('onEnterCancelled', async () => {}, E2E_TIMEOUT)
- test.todo('transition on appear', async () => {}, E2E_TIMEOUT)
+ test(
+ 'onEnterCancelled',
+ async () => {
+ const btnSelector = '.if-enter-cancelled > button'
+ const containerSelector = '.if-enter-cancelled > div'
+ const childSelector = `${containerSelector} > div`
+
+ expect(await html(containerSelector)).toBe('')
+
+ // enter
+ expect(
+ (await transitionStart(btnSelector, childSelector)).classNames,
+ ).toStrictEqual(['test', 'test-enter-from', 'test-enter-active'])
+ await nextFrame()
+ expect(await classList(childSelector)).toStrictEqual([
+ 'test',
+ 'test-enter-active',
+ 'test-enter-to',
+ ])
+
+ // cancel (leave)
+ expect(
+ (await transitionStart(btnSelector, childSelector)).classNames,
+ ).toStrictEqual(['test', 'test-leave-from', 'test-leave-active'])
+ let calls = await page().evaluate(() => {
+ return (window as any).getCalls('enterCancel')
+ })
+ expect(calls).toStrictEqual(['enterCancelled'])
+ await nextFrame()
+ expect(await classList(childSelector)).toStrictEqual([
+ 'test',
+ 'test-leave-active',
+ 'test-leave-to',
+ ])
+ await transitionFinish()
+ expect(await html(containerSelector)).toBe('')
+ },
+ E2E_TIMEOUT,
+ )
+
+ test.todo(
+ 'transition on appear',
+ async () => {
+ const btnSelector = '.if-appear > button'
+ const containerSelector = '.if-appear > div'
+ const childSelector = `${containerSelector} > div`
+ },
+ E2E_TIMEOUT,
+ )
test.todo('transition events with appear', async () => {}, E2E_TIMEOUT)
test.todo('no transition detected', async () => {}, E2E_TIMEOUT)
test.todo('animations', async () => {}, E2E_TIMEOUT)
const toggle = ref(true)
const count = ref(0)
+const timeout = (fn, time) => setTimeout(fn, time)
+
let calls = {
basic: [],
withOutAppear: [],
- withArgs: []
+ withArgs: [],
+ enterCancel: [],
}
-window.getCalls = (key) => calls[key]
-window.resetCalls = (key) => calls[key] = []
+window.getCalls = key => calls[key]
+window.resetCalls = key => (calls[key] = [])
import VaporCompA from './components/VaporCompA.vue'
import VaporCompB from './components/VaporCompB.vue'
</div>
<div class="if-custom-classes">
<div>
- <transition enter-from-class="hello-from" enter-active-class="hello-active" enter-to-class="hello-to"
- leave-from-class="bye-from" leave-active-class="bye-active" leave-to-class="bye-to">
+ <transition
+ enter-from-class="hello-from"
+ enter-active-class="hello-active"
+ enter-to-class="hello-to"
+ leave-from-class="bye-from"
+ leave-active-class="bye-active"
+ leave-to-class="bye-to"
+ >
<div v-if="toggle" class="test">content</div>
</transition>
</div>
</div>
<div class="if-events-without-appear">
<div>
- <transition name="test" @before-enter="() => calls.withOutAppear.push('beforeEnter')"
- @enter="() => calls.withOutAppear.push('onEnter')" @after-enter="() => calls.withOutAppear.push('afterEnter')"
+ <transition
+ name="test"
+ @before-enter="() => calls.withOutAppear.push('beforeEnter')"
+ @enter="() => calls.withOutAppear.push('onEnter')"
+ @after-enter="() => calls.withOutAppear.push('afterEnter')"
@beforeLeave="() => calls.withOutAppear.push('beforeLeave')"
- @leave="() => calls.withOutAppear.push('onLeave')" @afterLeave="() => calls.withOutAppear.push('afterLeave')">
+ @leave="() => calls.withOutAppear.push('onLeave')"
+ @afterLeave="() => calls.withOutAppear.push('afterLeave')"
+ >
<div v-if="toggle" class="test">content</div>
</transition>
</div>
</div>
<div class="if-events-with-args">
<div id="container">
- <transition :css="false" name="test" @before-enter="(el) => {
- calls.withArgs.push('beforeEnter');
- el.classList.add('before-enter')
- }" @enter="(el, done) => {
- calls.withArgs.push('onEnter');
- el.classList.add('enter')
- setTimeout(done, 200)
- }" @after-enter="(el) => {
- calls.withArgs.push('afterEnter');
- el.classList.add('after-enter')
- }" @before-leave="(el) => {
- calls.withArgs.push('beforeLeave');
- el.classList.add('before-leave')
- }" @leave="(el, done) => {
- calls.withArgs.push('onLeave');
- el.classList.add('leave')
- setTimeout(done, 200)
- }" @after-leave="() => {
- calls.withArgs.push('afterLeave');
- }">
+ <transition
+ :css="false"
+ name="test"
+ @before-enter="
+ el => {
+ calls.withArgs.push('beforeEnter')
+ el.classList.add('before-enter')
+ }
+ "
+ @enter="
+ (el, done) => {
+ calls.withArgs.push('onEnter')
+ el.classList.add('enter')
+ timeout(done, 200)
+ }
+ "
+ @after-enter="
+ el => {
+ calls.withArgs.push('afterEnter')
+ el.classList.add('after-enter')
+ }
+ "
+ @before-leave="
+ el => {
+ calls.withArgs.push('beforeLeave')
+ el.classList.add('before-leave')
+ }
+ "
+ @leave="
+ (el, done) => {
+ calls.withArgs.push('onLeave')
+ el.classList.add('leave')
+ timeout(done, 200)
+ }
+ "
+ @after-leave="
+ () => {
+ calls.withArgs.push('afterLeave')
+ }
+ "
+ >
<div v-if="toggle" class="test">content</div>
</transition>
</div>
<button id="toggleBtn" @click="toggle = !toggle">button</button>
</div>
+ <div class="if-enter-cancelled">
+ <div>
+ <transition
+ name="test"
+ @enter-cancelled="
+ () => {
+ calls.enterCancel.push('enterCancelled')
+ }
+ "
+ >
+ <div v-if="!toggle" class="test">content</div>
+ </transition>
+ </div>
+ <button @click="toggle = !toggle">cancelled</button>
+ </div>
+ <div class="if-appear">
+ <div>
+ <transition
+ name="test"
+ appear
+ appear-from-class="test-appear-from"
+ appear-to-class="test-appear-to"
+ appear-active-class="test-appear-active"
+ >
+ <div v-if="toggle" class="test">content</div>
+ </transition>
+ </div>
+ <button @click="toggle = !toggle">button</button>
+ </div>
<div class="vshow">
<button @click="show = !show">Show</button>
</div>
<div class="vif">
<button @click="toggle = !toggle">Toggle</button>
- <Transition appear @beforeEnter="() => calls.basic.push('beforeEnter')" @enter="() => calls.basic.push('onEnter')"
- @afterEnter="() => calls.basic.push('afterEnter')" @beforeLeave="() => calls.basic.push('beforeLeave')"
- @leave="() => calls.basic.push('onLeave')" @afterLeave="() => calls.basic.push('afterLeave')"
- @beforeAppear="() => calls.basic.push('beforeAppear')" @appear="() => calls.basic.push('onAppear')"
- @afterAppear="() => calls.basic.push('afterAppear')">
+ <Transition
+ appear
+ @beforeEnter="() => calls.basic.push('beforeEnter')"
+ @enter="() => calls.basic.push('onEnter')"
+ @afterEnter="() => calls.basic.push('afterEnter')"
+ @beforeLeave="() => calls.basic.push('beforeLeave')"
+ @leave="() => calls.basic.push('onLeave')"
+ @afterLeave="() => calls.basic.push('afterLeave')"
+ @beforeAppear="() => calls.basic.push('beforeAppear')"
+ @appear="() => calls.basic.push('onAppear')"
+ @afterAppear="() => calls.basic.push('afterAppear')"
+ >
<h1 v-if="toggle">vIf</h1>
</Transition>
</div>
}
</style>
<style>
-.transition-container>div {
+.transition-container > div {
padding: 15px;
border: 1px solid #f7f7f7;
margin-top: 15px;
checkTransitionMode(mode)
let resolvedProps
+ let isMounted = false
renderEffect(() => {
resolvedProps = resolveTransitionProps(props)
- // only update props for Fragment block, for later reusing
- if (isFragment(children) && children.$transition) {
- children.$transition.props = resolvedProps
- } else {
- // replace existing transition hooks
- const child = findTransitionBlock(children)
- if (child && child.$transition) {
- child.$transition.props = resolvedProps
- applyTransitionHooks(child, child.$transition)
+ if (isMounted) {
+ // only update props for Fragment block, for later reusing
+ if (isFragment(children)) {
+ if (children.$transition) children.$transition.props = resolvedProps
+ } else {
+ // replace existing transition hooks
+ const child = findTransitionBlock(children)
+ if (child && child.$transition) {
+ child.$transition.props = resolvedProps
+ applyTransitionHooks(child, child.$transition)
+ }
}
+ } else {
+ isMounted = true
}
})
block: Block,
hooks: VaporTransitionHooks,
): VaporTransitionHooks {
- const child = findTransitionBlock(block)
- if (!child) return hooks
+ const inFragment = isFragment(block)
+ const child = findTransitionBlock(block, inFragment)
+ if (!child) {
+ // set transition hooks on fragment for reusing during it's updating
+ if (inFragment) setTransitionHooksToFragment(block, hooks)
+ return hooks
+ }
const { props, state, delayedLeave } = hooks
let resolvedHooks = resolveTransitionHooks(
)
resolvedHooks.delayedLeave = delayedLeave
setTransitionHooks(child, resolvedHooks)
- if (isFragment(block)) {
- // also set transition hooks on fragment for reusing during it's updating
- setTransitionHooksToFragment(block, resolvedHooks)
- }
+ if (inFragment) setTransitionHooksToFragment(block, resolvedHooks)
return resolvedHooks
}
}
const transitionBlockCache = new WeakMap<Block, TransitionBlock>()
-export function findTransitionBlock(block: Block): TransitionBlock | undefined {
+export function findTransitionBlock(
+ block: Block,
+ inFragment: boolean = false,
+): TransitionBlock | undefined {
if (transitionBlockCache.has(block)) {
return transitionBlockCache.get(block)
}
if (block.insert) {
child = block
} else {
- child = findTransitionBlock(block.nodes)
+ child = findTransitionBlock(block.nodes, true)
}
}
- if (__DEV__ && !child) {
+ if (__DEV__ && !child && !inFragment) {
warn('Transition component has no valid child element')
}