diff --git a/packages/runtime-core/src/createRenderer.ts b/packages/runtime-core/src/createRenderer.ts index d9aa3f06..14ebb90f 100644 --- a/packages/runtime-core/src/createRenderer.ts +++ b/packages/runtime-core/src/createRenderer.ts @@ -26,7 +26,6 @@ import { EMPTY_ARR, isReservedProp, isFunction, - isArray, PatchFlags } from '@vue/shared' import { queueJob, queuePostFlushCb, flushPostFlushCbs } from './scheduler' @@ -46,7 +45,11 @@ import { pushWarningContext, popWarningContext, warn } from './warning' import { invokeDirectiveHook } from './directives' import { ComponentPublicInstance } from './componentProxy' import { App, createAppAPI } from './apiApp' -import { SuspenseBoundary, SuspenseImpl } from './suspense' +import { + SuspenseBoundary, + SuspenseImpl, + queueEffectWithSuspense +} from './suspense' import { ErrorCodes, callWithErrorHandling } from './errorHandling' export interface RendererOptions { @@ -135,20 +138,7 @@ function invokeHooks(hooks: Function[], arg?: DebuggerEvent) { } export const queuePostRenderEffect = __FEATURE_SUSPENSE__ - ? ( - fn: Function | Function[], - suspense: SuspenseBoundary | null - ) => { - if (suspense !== null && !suspense.isResolved) { - if (isArray(fn)) { - suspense.effects.push(...fn) - } else { - suspense.effects.push(fn) - } - } else { - queuePostFlushCb(fn) - } - } + ? queueEffectWithSuspense : queuePostFlushCb /** @@ -1354,13 +1344,7 @@ export function createRenderer< return } if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) { - const suspense = vnode.suspense! - move( - suspense.isResolved ? suspense.subTree : suspense.fallbackTree, - container, - anchor - ) - suspense.container = container + vnode.suspense!.move(container, anchor) return } if (vnode.type === Fragment) { @@ -1503,10 +1487,7 @@ export function createRenderer< return getNextHostNode(vnode.component!.subTree) } if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) { - const suspense = vnode.suspense! - return getNextHostNode( - suspense.isResolved ? suspense.subTree : suspense.fallbackTree - ) + return vnode.suspense!.next() } return hostNextSibling((vnode.anchor || vnode.el)!) } diff --git a/packages/runtime-core/src/suspense.ts b/packages/runtime-core/src/suspense.ts index 251dcd41..2a7019c7 100644 --- a/packages/runtime-core/src/suspense.ts +++ b/packages/runtime-core/src/suspense.ts @@ -1,6 +1,6 @@ import { VNode, normalizeVNode, VNodeChild, VNodeTypes } from './vnode' import { ShapeFlags } from './shapeFlags' -import { isFunction } from '@vue/shared' +import { isFunction, isArray } from '@vue/shared' import { ComponentInternalInstance, handleSetupResult } from './component' import { Slots } from './componentSlots' import { RendererInternals } from './createRenderer' @@ -197,6 +197,8 @@ export interface SuspenseBoundary< effects: Function[] resolve(): void restart(): void + move(container: HostElement, anchor: HostNode | null): void + next(): HostNode | null registerDep( instance: ComponentInternalInstance, setupRenderEffect: ( @@ -354,6 +356,21 @@ function createSuspenseBoundary( } }, + move(container, anchor) { + move( + suspense.isResolved ? suspense.subTree : suspense.fallbackTree, + container, + anchor + ) + suspense.container = container + }, + + next() { + return next( + suspense.isResolved ? suspense.subTree : suspense.fallbackTree + ) + }, + registerDep(instance, setupRenderEffect) { // suspense is already resolved, need to recede. // use queueJob so it's handled synchronously after patching the current @@ -439,3 +456,18 @@ function normalizeSuspenseChildren( } } } + +export function queueEffectWithSuspense( + fn: Function | Function[], + suspense: SuspenseBoundary | null +): void { + if (suspense !== null && !suspense.isResolved) { + if (isArray(fn)) { + suspense.effects.push(...fn) + } else { + suspense.effects.push(fn) + } + } else { + queuePostFlushCb(fn) + } +}