feat(transition): compat with keep-alive
This commit is contained in:
parent
16ea2993d6
commit
c6fb506fc0
@ -347,12 +347,8 @@ describe('compiler: element transform', () => {
|
||||
expect(node.arguments).toMatchObject([
|
||||
KEEP_ALIVE,
|
||||
`null`,
|
||||
createObjectMatcher({
|
||||
default: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION
|
||||
},
|
||||
_compiled: `[true]`
|
||||
})
|
||||
// keep-alive should not compile content to slots
|
||||
[{ type: NodeTypes.ELEMENT, tag: 'span' }]
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -138,8 +138,11 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||
if (!hasProps) {
|
||||
args.push(`null`)
|
||||
}
|
||||
// Portal should have normal children instead of slots
|
||||
if (isComponent && !isPortal) {
|
||||
// Portal & KeepAlive should have normal children instead of slots
|
||||
// Portal is not a real component has dedicated handling in the renderer
|
||||
// KeepAlive should not track its own deps so that it can be used inside
|
||||
// Transition
|
||||
if (isComponent && !isPortal && !isKeepAlive) {
|
||||
const { slots, hasDynamicSlots } = buildSlots(node, context)
|
||||
args.push(slots)
|
||||
if (hasDynamicSlots) {
|
||||
|
@ -91,7 +91,8 @@ export function renderComponentRoot(
|
||||
if (
|
||||
__DEV__ &&
|
||||
!(result.shapeFlag & ShapeFlags.COMPONENT) &&
|
||||
!(result.shapeFlag & ShapeFlags.ELEMENT)
|
||||
!(result.shapeFlag & ShapeFlags.ELEMENT) &&
|
||||
result.type !== Comment
|
||||
) {
|
||||
warn(
|
||||
`Component inside <Transition> renders non-element root node ` +
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { ComponentInternalInstance, currentInstance } from './component'
|
||||
import { VNode, NormalizedChildren, normalizeVNode, VNodeChild } from './vnode'
|
||||
import { isArray, isFunction } from '@vue/shared'
|
||||
import { isArray, isFunction, EMPTY_OBJ } from '@vue/shared'
|
||||
import { ShapeFlags } from './shapeFlags'
|
||||
import { warn } from './warning'
|
||||
import { isKeepAlive } from './components/KeepAlive'
|
||||
|
||||
export type Slot = (...args: any[]) => VNode[]
|
||||
|
||||
@ -65,7 +66,7 @@ export function resolveSlots(
|
||||
}
|
||||
} else if (children !== null) {
|
||||
// non slot object children (direct value) passed to a component
|
||||
if (__DEV__) {
|
||||
if (__DEV__ && !isKeepAlive(instance.vnode)) {
|
||||
warn(
|
||||
`Non-function value encountered for default slot. ` +
|
||||
`Prefer function slots for better performance.`
|
||||
@ -74,7 +75,5 @@ export function resolveSlots(
|
||||
const normalized = normalizeSlotValue(children)
|
||||
slots = { default: () => normalized }
|
||||
}
|
||||
if (slots !== void 0) {
|
||||
instance.slots = slots
|
||||
}
|
||||
instance.slots = slots || EMPTY_OBJ
|
||||
}
|
||||
|
@ -3,7 +3,13 @@ import {
|
||||
SetupContext,
|
||||
ComponentOptions
|
||||
} from '../component'
|
||||
import { cloneVNode, Comment, isSameVNodeType, VNode } from '../vnode'
|
||||
import {
|
||||
cloneVNode,
|
||||
Comment,
|
||||
isSameVNodeType,
|
||||
VNode,
|
||||
VNodeChildren
|
||||
} from '../vnode'
|
||||
import { warn } from '../warning'
|
||||
import { isKeepAlive } from './KeepAlive'
|
||||
import { toRaw } from '@vue/reactivity'
|
||||
@ -36,17 +42,38 @@ export interface BaseTransitionProps {
|
||||
onLeaveCancelled?: (el: any) => void
|
||||
}
|
||||
|
||||
export interface TransitionHooks {
|
||||
persisted: boolean
|
||||
beforeEnter(el: object): void
|
||||
enter(el: object): void
|
||||
leave(el: object, remove: () => void): void
|
||||
afterLeave?(): void
|
||||
delayLeave?(delayedLeave: () => void): void
|
||||
delayedLeave?(): void
|
||||
}
|
||||
|
||||
type TransitionHookCaller = (
|
||||
hook: ((el: any) => void) | undefined,
|
||||
args?: any[]
|
||||
) => void
|
||||
|
||||
type PendingCallback = (cancelled?: boolean) => void
|
||||
|
||||
interface TransitionState {
|
||||
isMounted: boolean
|
||||
isLeaving: boolean
|
||||
isUnmounting: boolean
|
||||
pendingEnter?: (cancelled?: boolean) => void
|
||||
pendingLeave?: (cancelled?: boolean) => void
|
||||
// Track pending leave callbacks for children of the same key.
|
||||
// This is used to force remove leaving a child when a new copy is entering.
|
||||
leavingVNodes: Record<string, VNode>
|
||||
}
|
||||
|
||||
interface TransitionElement {
|
||||
// in persisted mode (e.g. v-show), the same element is toggled, so the
|
||||
// pending enter/leave callbacks may need to cancalled if the state is toggled
|
||||
// before it finishes.
|
||||
_enterCb?: PendingCallback
|
||||
_leaveCb?: PendingCallback
|
||||
}
|
||||
|
||||
const BaseTransitionImpl = {
|
||||
@ -56,7 +83,8 @@ const BaseTransitionImpl = {
|
||||
const state: TransitionState = {
|
||||
isMounted: false,
|
||||
isLeaving: false,
|
||||
isUnmounting: false
|
||||
isUnmounting: false,
|
||||
leavingVNodes: Object.create(null)
|
||||
}
|
||||
onMounted(() => {
|
||||
state.isMounted = true
|
||||
@ -84,7 +112,7 @@ const BaseTransitionImpl = {
|
||||
// warn multiple elements
|
||||
if (__DEV__ && children.length > 1) {
|
||||
warn(
|
||||
'<transition> can only be used on a single element. Use ' +
|
||||
'<transition> can only be used on a single element or component. Use ' +
|
||||
'<transition-group> for lists.'
|
||||
)
|
||||
}
|
||||
@ -101,45 +129,53 @@ const BaseTransitionImpl = {
|
||||
// at this point children has a guaranteed length of 1.
|
||||
const child = children[0]
|
||||
if (state.isLeaving) {
|
||||
return placeholder(child)
|
||||
return emptyPlaceholder(child)
|
||||
}
|
||||
|
||||
let delayedLeave: (() => void) | undefined
|
||||
const performDelayedLeave = () => delayedLeave && delayedLeave()
|
||||
// in the case of <transition><keep-alive/></transition>, we need to
|
||||
// compare the type of the kept-alive children.
|
||||
const innerChild = getKeepAliveChild(child)
|
||||
if (!innerChild) {
|
||||
return emptyPlaceholder(child)
|
||||
}
|
||||
|
||||
const transitionHooks = (child.transition = resolveTransitionHooks(
|
||||
const enterHooks = (innerChild.transition = resolveTransitionHooks(
|
||||
innerChild,
|
||||
rawProps,
|
||||
state,
|
||||
callTransitionHook,
|
||||
performDelayedLeave
|
||||
callTransitionHook
|
||||
))
|
||||
|
||||
// clone old subTree because we need to modify it
|
||||
const oldChild = instance.subTree
|
||||
? (instance.subTree = cloneVNode(instance.subTree))
|
||||
: null
|
||||
|
||||
const oldInnerChild = oldChild && getKeepAliveChild(oldChild)
|
||||
// handle mode
|
||||
if (
|
||||
oldChild &&
|
||||
!isSameVNodeType(child, oldChild) &&
|
||||
oldChild.type !== Comment
|
||||
oldInnerChild &&
|
||||
oldInnerChild.type !== Comment &&
|
||||
!isSameVNodeType(innerChild, oldInnerChild)
|
||||
) {
|
||||
const prevHooks = oldInnerChild.transition!
|
||||
const leavingHooks = resolveTransitionHooks(
|
||||
oldInnerChild,
|
||||
rawProps,
|
||||
state,
|
||||
callTransitionHook
|
||||
)
|
||||
// update old tree's hooks in case of dynamic transition
|
||||
// need to do this recursively in case of HOCs
|
||||
updateHOCTransitionData(oldChild, transitionHooks)
|
||||
setTransitionHooks(oldInnerChild, leavingHooks)
|
||||
// switching between different views
|
||||
if (mode === 'out-in') {
|
||||
state.isLeaving = true
|
||||
// return placeholder node and queue update when leave finishes
|
||||
transitionHooks.afterLeave = () => {
|
||||
leavingHooks.afterLeave = () => {
|
||||
state.isLeaving = false
|
||||
instance.update()
|
||||
}
|
||||
return placeholder(child)
|
||||
return emptyPlaceholder(child)
|
||||
} else if (mode === 'in-out') {
|
||||
transitionHooks.delayLeave = performLeave => {
|
||||
delayedLeave = performLeave
|
||||
delete prevHooks.delayedLeave
|
||||
leavingHooks.delayLeave = delayedLeave => {
|
||||
enterHooks.delayedLeave = delayedLeave
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -175,18 +211,10 @@ export const BaseTransition = (BaseTransitionImpl as any) as {
|
||||
}
|
||||
}
|
||||
|
||||
export interface TransitionHooks {
|
||||
persisted: boolean
|
||||
beforeEnter(el: object): void
|
||||
enter(el: object): void
|
||||
leave(el: object, remove: () => void): void
|
||||
afterLeave?(): void
|
||||
delayLeave?(performLeave: () => void): void
|
||||
}
|
||||
|
||||
// The transition hooks are attached to the vnode as vnode.transition
|
||||
// and will be called at appropriate timing in the renderer.
|
||||
function resolveTransitionHooks(
|
||||
vnode: VNode,
|
||||
{
|
||||
appear,
|
||||
persisted = false,
|
||||
@ -200,36 +228,51 @@ function resolveTransitionHooks(
|
||||
onLeaveCancelled
|
||||
}: BaseTransitionProps,
|
||||
state: TransitionState,
|
||||
callHook: TransitionHookCaller,
|
||||
performDelayedLeave: () => void
|
||||
callHook: TransitionHookCaller
|
||||
): TransitionHooks {
|
||||
return {
|
||||
const { leavingVNodes } = state
|
||||
const key = String(vnode.key)
|
||||
|
||||
const hooks: TransitionHooks = {
|
||||
persisted,
|
||||
beforeEnter(el) {
|
||||
if (state.pendingLeave) {
|
||||
state.pendingLeave(true /* cancelled */)
|
||||
}
|
||||
beforeEnter(el: TransitionElement) {
|
||||
if (!appear && !state.isMounted) {
|
||||
return
|
||||
}
|
||||
// for same element (v-show)
|
||||
if (el._leaveCb) {
|
||||
el._leaveCb(true /* cancelled */)
|
||||
}
|
||||
// for toggled element with same key (v-if)
|
||||
const leavingVNode = leavingVNodes[key]
|
||||
if (
|
||||
leavingVNode &&
|
||||
isSameVNodeType(vnode, leavingVNode) &&
|
||||
leavingVNode.el._leaveCb
|
||||
) {
|
||||
// force early removal (not cancelled)
|
||||
leavingVNode.el._leaveCb()
|
||||
}
|
||||
callHook(onBeforeEnter, [el])
|
||||
},
|
||||
|
||||
enter(el) {
|
||||
enter(el: TransitionElement) {
|
||||
if (!appear && !state.isMounted) {
|
||||
return
|
||||
}
|
||||
let called = false
|
||||
const afterEnter = (state.pendingEnter = (cancelled?) => {
|
||||
const afterEnter = (el._enterCb = (cancelled?) => {
|
||||
if (called) return
|
||||
called = true
|
||||
if (cancelled) {
|
||||
callHook(onEnterCancelled, [el])
|
||||
} else {
|
||||
callHook(onAfterEnter, [el])
|
||||
performDelayedLeave()
|
||||
}
|
||||
state.pendingEnter = undefined
|
||||
if (hooks.delayedLeave) {
|
||||
hooks.delayedLeave()
|
||||
}
|
||||
el._enterCb = undefined
|
||||
})
|
||||
if (onEnter) {
|
||||
onEnter(el, afterEnter)
|
||||
@ -238,16 +281,17 @@ function resolveTransitionHooks(
|
||||
}
|
||||
},
|
||||
|
||||
leave(el, remove) {
|
||||
if (state.pendingEnter) {
|
||||
state.pendingEnter(true /* cancelled */)
|
||||
leave(el: TransitionElement, remove) {
|
||||
const key = String(vnode.key)
|
||||
if (el._enterCb) {
|
||||
el._enterCb(true /* cancelled */)
|
||||
}
|
||||
if (state.isUnmounting) {
|
||||
return remove()
|
||||
}
|
||||
callHook(onBeforeLeave, [el])
|
||||
let called = false
|
||||
const afterLeave = (state.pendingLeave = (cancelled?) => {
|
||||
const afterLeave = (el._leaveCb = (cancelled?) => {
|
||||
if (called) return
|
||||
called = true
|
||||
remove()
|
||||
@ -256,8 +300,10 @@ function resolveTransitionHooks(
|
||||
} else {
|
||||
callHook(onAfterLeave, [el])
|
||||
}
|
||||
state.pendingLeave = undefined
|
||||
el._leaveCb = undefined
|
||||
delete leavingVNodes[key]
|
||||
})
|
||||
leavingVNodes[key] = vnode
|
||||
if (onLeave) {
|
||||
onLeave(el, afterLeave)
|
||||
} else {
|
||||
@ -265,13 +311,15 @@ function resolveTransitionHooks(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hooks
|
||||
}
|
||||
|
||||
// the placeholder really only handles one special case: KeepAlive
|
||||
// in the case of a KeepAlive in a leave phase we need to return a KeepAlive
|
||||
// placeholder with empty content to avoid the KeepAlive instance from being
|
||||
// unmounted.
|
||||
function placeholder(vnode: VNode): VNode | undefined {
|
||||
function emptyPlaceholder(vnode: VNode): VNode | undefined {
|
||||
if (isKeepAlive(vnode)) {
|
||||
vnode = cloneVNode(vnode)
|
||||
vnode.children = null
|
||||
@ -279,10 +327,18 @@ function placeholder(vnode: VNode): VNode | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
function updateHOCTransitionData(vnode: VNode, data: TransitionHooks) {
|
||||
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
||||
updateHOCTransitionData(vnode.component!.subTree, data)
|
||||
function getKeepAliveChild(vnode: VNode): VNode | undefined {
|
||||
return isKeepAlive(vnode)
|
||||
? vnode.children
|
||||
? ((vnode.children as VNodeChildren)[0] as VNode)
|
||||
: undefined
|
||||
: vnode
|
||||
}
|
||||
|
||||
export function setTransitionHooks(vnode: VNode, hooks: TransitionHooks) {
|
||||
if (vnode.shapeFlag & ShapeFlags.COMPONENT && vnode.component) {
|
||||
setTransitionHooks(vnode.component.subTree, hooks)
|
||||
} else {
|
||||
vnode.transition = data
|
||||
vnode.transition = hooks
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,10 @@ import { SuspenseBoundary } from './Suspense'
|
||||
import {
|
||||
RendererInternals,
|
||||
queuePostRenderEffect,
|
||||
invokeHooks
|
||||
invokeHooks,
|
||||
MoveType
|
||||
} from '../renderer'
|
||||
import { setTransitionHooks } from './BaseTransition'
|
||||
|
||||
type MatchPattern = string | RegExp | string[] | RegExp[]
|
||||
|
||||
@ -80,7 +82,7 @@ const KeepAliveImpl = {
|
||||
const storageContainer = createElement('div')
|
||||
|
||||
sink.activate = (vnode, container, anchor) => {
|
||||
move(vnode, container, anchor)
|
||||
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
|
||||
queuePostRenderEffect(() => {
|
||||
const component = vnode.component!
|
||||
component.isDeactivated = false
|
||||
@ -91,7 +93,7 @@ const KeepAliveImpl = {
|
||||
}
|
||||
|
||||
sink.deactivate = (vnode: VNode) => {
|
||||
move(vnode, storageContainer, null)
|
||||
move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)
|
||||
queuePostRenderEffect(() => {
|
||||
const component = vnode.component!
|
||||
if (component.da !== null) {
|
||||
@ -188,6 +190,10 @@ const KeepAliveImpl = {
|
||||
vnode.el = cached.el
|
||||
vnode.anchor = cached.anchor
|
||||
vnode.component = cached.component
|
||||
if (vnode.transition) {
|
||||
// recursively update transition hooks on subTree
|
||||
setTransitionHooks(vnode, vnode.transition!)
|
||||
}
|
||||
// avoid vnode being mounted as fresh
|
||||
vnode.shapeFlag |= ShapeFlags.COMPONENT_KEPT_ALIVE
|
||||
// make this key the freshest
|
||||
|
@ -3,7 +3,7 @@ import { ShapeFlags } from '../shapeFlags'
|
||||
import { isFunction, isArray } from '@vue/shared'
|
||||
import { ComponentInternalInstance, handleSetupResult } from '../component'
|
||||
import { Slots } from '../componentSlots'
|
||||
import { RendererInternals } from '../renderer'
|
||||
import { RendererInternals, MoveType } from '../renderer'
|
||||
import { queuePostFlushCb, queueJob } from '../scheduler'
|
||||
import { updateHOCHostEl } from '../componentRenderUtils'
|
||||
import { handleError, ErrorCodes } from '../errorHandling'
|
||||
@ -213,7 +213,7 @@ export interface SuspenseBoundary<
|
||||
effects: Function[]
|
||||
resolve(): void
|
||||
recede(): void
|
||||
move(container: HostElement, anchor: HostNode | null): void
|
||||
move(container: HostElement, anchor: HostNode | null, type: MoveType): void
|
||||
next(): HostNode | null
|
||||
registerDep(
|
||||
instance: ComponentInternalInstance,
|
||||
@ -299,7 +299,7 @@ function createSuspenseBoundary<HostNode, HostElement>(
|
||||
unmount(fallbackTree as VNode, parentComponent, suspense, true)
|
||||
}
|
||||
// move content from off-dom container to actual container
|
||||
move(subTree as VNode, container, anchor)
|
||||
move(subTree as VNode, container, anchor, MoveType.ENTER)
|
||||
const el = (vnode.el = (subTree as VNode).el!)
|
||||
// suspense as the root node of a component...
|
||||
if (parentComponent && parentComponent.subTree === vnode) {
|
||||
@ -346,7 +346,7 @@ function createSuspenseBoundary<HostNode, HostElement>(
|
||||
|
||||
// move content tree back to the off-dom container
|
||||
const anchor = next(subTree)
|
||||
move(subTree as VNode, hiddenContainer, null)
|
||||
move(subTree as VNode, hiddenContainer, null, MoveType.LEAVE)
|
||||
// remount the fallback tree
|
||||
patch(
|
||||
null,
|
||||
@ -372,11 +372,12 @@ function createSuspenseBoundary<HostNode, HostElement>(
|
||||
}
|
||||
},
|
||||
|
||||
move(container, anchor) {
|
||||
move(container, anchor, type) {
|
||||
move(
|
||||
suspense.isResolved ? suspense.subTree : suspense.fallbackTree,
|
||||
container,
|
||||
anchor
|
||||
anchor,
|
||||
type
|
||||
)
|
||||
suspense.container = container
|
||||
},
|
||||
|
@ -109,12 +109,20 @@ export interface RendererInternals<HostNode = any, HostElement = any> {
|
||||
move: (
|
||||
vnode: VNode<HostNode, HostElement>,
|
||||
container: HostElement,
|
||||
anchor: HostNode | null
|
||||
anchor: HostNode | null,
|
||||
type: MoveType,
|
||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null
|
||||
) => void
|
||||
next: (vnode: VNode<HostNode, HostElement>) => HostNode | null
|
||||
options: RendererOptions<HostNode, HostElement>
|
||||
}
|
||||
|
||||
export const enum MoveType {
|
||||
ENTER,
|
||||
LEAVE,
|
||||
REORDER
|
||||
}
|
||||
|
||||
const prodEffectOptions = {
|
||||
scheduler: queueJob
|
||||
}
|
||||
@ -367,9 +375,6 @@ export function createRenderer<
|
||||
invokeDirectiveHook(props.onVnodeBeforeMount, parentComponent, vnode)
|
||||
}
|
||||
}
|
||||
if (transition != null && !transition.persisted) {
|
||||
transition.beforeEnter(el)
|
||||
}
|
||||
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
||||
hostSetElementText(el, vnode.children as string)
|
||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||
@ -383,6 +388,9 @@ export function createRenderer<
|
||||
optimized || vnode.dynamicChildren !== null
|
||||
)
|
||||
}
|
||||
if (transition != null && !transition.persisted) {
|
||||
transition.beforeEnter(el)
|
||||
}
|
||||
hostInsert(el, container, anchor)
|
||||
const vnodeMountedHook = props && props.onVnodeMounted
|
||||
if (
|
||||
@ -747,7 +755,12 @@ export function createRenderer<
|
||||
hostSetElementText(nextTarget, children as string)
|
||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||
for (let i = 0; i < (children as HostVNode[]).length; i++) {
|
||||
move((children as HostVNode[])[i], nextTarget, null)
|
||||
move(
|
||||
(children as HostVNode[])[i],
|
||||
nextTarget,
|
||||
null,
|
||||
MoveType.REORDER
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (__DEV__) {
|
||||
@ -1372,7 +1385,7 @@ export function createRenderer<
|
||||
// There is no stable subsequence (e.g. a reverse)
|
||||
// OR current node is not among the stable sequence
|
||||
if (j < 0 || i !== increasingNewIndexSequence[j]) {
|
||||
move(nextChild, container, anchor)
|
||||
move(nextChild, container, anchor, MoveType.REORDER)
|
||||
} else {
|
||||
j--
|
||||
}
|
||||
@ -1384,25 +1397,54 @@ export function createRenderer<
|
||||
function move(
|
||||
vnode: HostVNode,
|
||||
container: HostElement,
|
||||
anchor: HostNode | null
|
||||
anchor: HostNode | null,
|
||||
type: MoveType,
|
||||
parentSuspense: HostSuspenseBoundary | null = null
|
||||
) {
|
||||
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
||||
move(vnode.component!.subTree, container, anchor)
|
||||
move(vnode.component!.subTree, container, anchor, type)
|
||||
return
|
||||
}
|
||||
if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {
|
||||
vnode.suspense!.move(container, anchor)
|
||||
vnode.suspense!.move(container, anchor, type)
|
||||
return
|
||||
}
|
||||
if (vnode.type === Fragment) {
|
||||
hostInsert(vnode.el!, container, anchor)
|
||||
const children = vnode.children as HostVNode[]
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
move(children[i], container, anchor)
|
||||
move(children[i], container, anchor, type)
|
||||
}
|
||||
hostInsert(vnode.anchor!, container, anchor)
|
||||
} else {
|
||||
hostInsert(vnode.el!, container, anchor)
|
||||
// Plain element
|
||||
const { el, transition, shapeFlag } = vnode
|
||||
const needTransition =
|
||||
type !== MoveType.REORDER &&
|
||||
shapeFlag & ShapeFlags.ELEMENT &&
|
||||
transition != null
|
||||
if (needTransition) {
|
||||
if (type === MoveType.ENTER) {
|
||||
transition!.beforeEnter(el!)
|
||||
hostInsert(el!, container, anchor)
|
||||
queuePostRenderEffect(() => transition!.enter(el!), parentSuspense)
|
||||
} else {
|
||||
const { leave, delayLeave, afterLeave } = transition!
|
||||
const performLeave = () => {
|
||||
leave(el!, () => {
|
||||
hostInsert(el!, container, anchor)
|
||||
afterLeave && afterLeave()
|
||||
})
|
||||
}
|
||||
if (delayLeave) {
|
||||
delayLeave(performLeave)
|
||||
} else {
|
||||
performLeave()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hostInsert(el!, container, anchor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user