'<div class="">vapor compA</div>',
)
})
+
+ test('apply transition to pre-resolved async component', async () => {
+ const btnSelector = '.async-resolved > button'
+ const containerSelector = '.async-resolved #container'
+ const hiddenCompSelector = '.async-resolved #hidden-async'
+
+ // Wait for the hidden AsyncCompResolved to resolve and render
+ await waitForInnerHTML(
+ hiddenCompSelector,
+ '<div style="display: none;">vapor compA</div>',
+ )
+
+ expect(await html(containerSelector)).toBe('')
+
+ await click(btnSelector)
+ expect(await html(containerSelector)).toBe(
+ '<div class="v-enter-from v-enter-active">vapor compA</div>',
+ )
+ await waitForInnerHTML(
+ containerSelector,
+ '<div class="v-enter-active v-enter-to">vapor compA</div>',
+ )
+ await waitForInnerHTML(
+ containerSelector,
+ '<div class="">vapor compA</div>',
+ )
+
+ // leave
+ await click(btnSelector)
+ await nextTick()
+ expect(await html(containerSelector)).toBe(
+ '<div class="v-leave-from v-leave-active">vapor compA</div>',
+ )
+ await waitForInnerHTML(
+ containerSelector,
+ '<div class="v-leave-active v-leave-to">vapor compA</div>',
+ )
+ await waitForInnerHTML(containerSelector, '')
+
+ // enter again
+ await click(btnSelector)
+ expect(await html(containerSelector)).toBe(
+ '<div class="v-enter-from v-enter-active">vapor compA</div>',
+ )
+ await waitForInnerHTML(
+ containerSelector,
+ '<div class="v-enter-active v-enter-to">vapor compA</div>',
+ )
+ await waitForInnerHTML(
+ containerSelector,
+ '<div class="">vapor compA</div>',
+ )
+ })
})
describe('transition with v-show', () => {
return new Promise(resolve => setTimeout(() => resolve(VaporCompA), 50))
})
+const AsyncCompResolved = defineVaporAsyncComponent(() =>
+ Promise.resolve(VaporCompA),
+)
+
const TrueBranch = defineVaporComponent({
name: 'TrueBranch',
setup() {
</div>
<button @click="toggle = !toggle">button</button>
</div>
+ <div class="async-resolved">
+ <!-- Pre-resolve the async component by rendering it hidden -->
+ <div id="hidden-async">
+ <AsyncCompResolved v-show="false" />
+ </div>
+ <div id="container">
+ <transition>
+ <AsyncCompResolved v-if="!toggle"></AsyncCompResolved>
+ </transition>
+ </div>
+ <button @click="toggle = !toggle">button</button>
+ </div>
<!-- async component end -->
<!-- with teleport -->
import { invokeArrayFns } from '@vue/shared'
import { type TransitionOptions, insert, remove } from './block'
import { parentNode } from './dom/node'
-import { setTransitionHooks } from './components/Transition'
/*@ __NO_SIDE_EFFECTS__ */
export function defineVaporAsyncComponent<T extends VaporComponent>(
render = () => createComponent(loadingComponent)
}
- if (instance.$transition) frag!.$transition = instance.$transition
frag.update(render)
// Manually trigger cacheBlock for KeepAlive
if (frag.keepAliveCtx) frag.keepAliveCtx.cacheBlock()
parent: VaporComponentInstance & TransitionOptions,
frag?: DynamicFragment,
): VaporComponentInstance {
- const { rawProps, rawSlots, appContext, $transition } = parent
+ const { rawProps, rawSlots, appContext } = parent
const instance = createComponent(
comp,
rawProps,
appContext,
)
- // set transition hooks
- if ($transition) setTransitionHooks(instance, $transition)
-
// set ref
frag && frag.setAsyncRef && frag.setAsyncRef(instance)
} from '../component'
import { isArray } from '@vue/shared'
import { renderEffect } from '../renderEffect'
-import { type VaporFragment, isFragment } from '../fragment'
+import {
+ type DynamicFragment,
+ type VaporFragment,
+ isFragment,
+} from '../fragment'
import {
currentHydrationNode,
isHydrating,
// transition can only be applied on Element child
if (block instanceof Element) child = block
} else if (isVaporComponent(block)) {
- // should save hooks on unresolved async wrapper, so that it can be applied after resolved
- if (isAsyncWrapper(block) && !block.type.__asyncResolved) {
- child = block
+ if (isAsyncWrapper(block)) {
+ // for unresolved async wrapper, set transition hooks on inner fragment
+ if (!block.type.__asyncResolved) {
+ onFragment && onFragment(block.block! as DynamicFragment)
+ } else {
+ child = findTransitionBlock(
+ (block.block! as DynamicFragment).nodes,
+ onFragment,
+ )
+ }
} else {
// stop searching if encountering nested Transition component
if (getComponentName(block.type) === displayName) return undefined