|
|
@@ -10,6 +10,7 @@ import {
|
|
|
isTeleportDisabled,
|
|
|
queuePostFlushCb,
|
|
|
resolveTeleportTarget,
|
|
|
+ setCurrentInstance,
|
|
|
warn,
|
|
|
} from '@vue/runtime-dom'
|
|
|
import {
|
|
|
@@ -24,12 +25,15 @@ import { createComment, createTextNode, querySelector } from '../dom/node'
|
|
|
import {
|
|
|
type LooseRawProps,
|
|
|
type LooseRawSlots,
|
|
|
+ type VaporComponentInstance,
|
|
|
+ currentInstance,
|
|
|
isVaporComponent,
|
|
|
} from '../component'
|
|
|
import { rawPropsProxyHandlers } from '../componentProps'
|
|
|
import { renderEffect } from '../renderEffect'
|
|
|
import { extend, isArray } from '@vue/shared'
|
|
|
import { VaporFragment, isFragment } from '../fragment'
|
|
|
+import { currentKeepAliveCtx, setCurrentKeepAliveCtx } from './KeepAlive'
|
|
|
import {
|
|
|
advanceHydrationNode,
|
|
|
currentHydrationNode,
|
|
|
@@ -40,7 +44,11 @@ import {
|
|
|
setCurrentHydrationNode,
|
|
|
} from '../dom/hydration'
|
|
|
import type { DefineVaporSetupFnComponent } from '../apiDefineComponent'
|
|
|
-import { getScopeOwner } from '../componentSlots'
|
|
|
+import {
|
|
|
+ currentSlotOwner,
|
|
|
+ getScopeOwner,
|
|
|
+ setCurrentSlotOwner,
|
|
|
+} from '../componentSlots'
|
|
|
|
|
|
const VaporTeleportImpl = {
|
|
|
name: 'VaporTeleport',
|
|
|
@@ -64,6 +72,11 @@ export class TeleportFragment extends VaporFragment {
|
|
|
private rawSlots?: LooseRawSlots
|
|
|
isDisabled?: boolean
|
|
|
private isMounted = false
|
|
|
+ private childrenInitialized = false
|
|
|
+ private readonly ownerInstance =
|
|
|
+ currentInstance as VaporComponentInstance | null
|
|
|
+ private readonly slotOwner = currentSlotOwner
|
|
|
+ private readonly keepAliveCtx = currentKeepAliveCtx
|
|
|
|
|
|
target?: ParentNode | null
|
|
|
targetAnchor?: Node | null
|
|
|
@@ -104,10 +117,6 @@ export class TeleportFragment extends VaporFragment {
|
|
|
this.handlePropsUpdate()
|
|
|
}
|
|
|
})
|
|
|
-
|
|
|
- if (!isHydrating) {
|
|
|
- this.initChildren()
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
get parent(): ParentNode | null {
|
|
|
@@ -115,12 +124,31 @@ export class TeleportFragment extends VaporFragment {
|
|
|
}
|
|
|
|
|
|
private initChildren(): void {
|
|
|
- renderEffect(() => {
|
|
|
- this.handleChildrenUpdate(
|
|
|
- this.rawSlots!.default && (this.rawSlots!.default as BlockFn)(),
|
|
|
- )
|
|
|
- })
|
|
|
- this.bindChildren(this.nodes)
|
|
|
+ const prevInstance = setCurrentInstance(this.ownerInstance)
|
|
|
+ try {
|
|
|
+ this.childrenInitialized = true
|
|
|
+ renderEffect(() => {
|
|
|
+ const prevOwner = setCurrentSlotOwner(this.slotOwner)
|
|
|
+ const prevKeepAliveCtx = setCurrentKeepAliveCtx(this.keepAliveCtx)
|
|
|
+ try {
|
|
|
+ this.handleChildrenUpdate(
|
|
|
+ this.rawSlots!.default && (this.rawSlots!.default as BlockFn)(),
|
|
|
+ )
|
|
|
+ } finally {
|
|
|
+ setCurrentKeepAliveCtx(prevKeepAliveCtx)
|
|
|
+ setCurrentSlotOwner(prevOwner)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.bindChildren(this.nodes)
|
|
|
+ } finally {
|
|
|
+ setCurrentInstance(...prevInstance)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ensureChildrenInitialized(): void {
|
|
|
+ if (!this.childrenInitialized) {
|
|
|
+ this.initChildren()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private registerUpdateCssVars(block: Block) {
|
|
|
@@ -155,8 +183,7 @@ export class TeleportFragment extends VaporFragment {
|
|
|
}
|
|
|
|
|
|
private handleChildrenUpdate(children: Block): void {
|
|
|
- // not mounted yet
|
|
|
- if (!this.parent || isHydrating || !this.mountContainer) {
|
|
|
+ if (isHydrating || !this.parent || !this.mountContainer) {
|
|
|
this.nodes = children
|
|
|
return
|
|
|
}
|
|
|
@@ -216,6 +243,8 @@ export class TeleportFragment extends VaporFragment {
|
|
|
insert((this.targetAnchor = createTextNode('')), target)
|
|
|
}
|
|
|
|
|
|
+ this.ensureChildrenInitialized()
|
|
|
+
|
|
|
// track CE teleport targets
|
|
|
if (this.parentComponent && this.parentComponent.isCE) {
|
|
|
;(
|
|
|
@@ -240,6 +269,7 @@ export class TeleportFragment extends VaporFragment {
|
|
|
|
|
|
// mount into main container
|
|
|
if (this.isDisabled) {
|
|
|
+ this.ensureChildrenInitialized()
|
|
|
this.mount(this.parent, this.anchor!)
|
|
|
}
|
|
|
// mount into target container
|
|
|
@@ -275,8 +305,8 @@ export class TeleportFragment extends VaporFragment {
|
|
|
|
|
|
remove = (parent: ParentNode | undefined = this.parent!): void => {
|
|
|
// remove nodes
|
|
|
- if (this.nodes) {
|
|
|
- remove(this.nodes, this.mountContainer!)
|
|
|
+ if (this.nodes && this.mountContainer) {
|
|
|
+ remove(this.nodes, this.mountContainer)
|
|
|
this.nodes = []
|
|
|
}
|
|
|
|
|
|
@@ -405,9 +435,9 @@ export class TeleportFragment extends VaporFragment {
|
|
|
this.hydrateDisabledTeleport(null, null)
|
|
|
} else {
|
|
|
// Align with VDOM Teleport hydration: keep main-view markers only and
|
|
|
- // avoid mounting children inline when the target is missing.
|
|
|
+ // avoid mounting children inline or eagerly initializing them when the
|
|
|
+ // target is missing.
|
|
|
this.anchor = locateTeleportEndAnchor(currentHydrationNode!.nextSibling!)!
|
|
|
- runWithoutHydration(this.initChildren.bind(this))
|
|
|
}
|
|
|
|
|
|
if (target || disabled) {
|