From: daiwei Date: Fri, 21 Mar 2025 13:53:35 +0000 (+0800) Subject: wip: save X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5c8f7ed2add8e6022e744912225d7a5ba381d963;p=thirdparty%2Fvuejs%2Fcore.git wip: save --- diff --git a/packages/runtime-vapor/src/components/Teleport.ts b/packages/runtime-vapor/src/components/Teleport.ts index 4b029b6412..823f6c5cca 100644 --- a/packages/runtime-vapor/src/components/Teleport.ts +++ b/packages/runtime-vapor/src/components/Teleport.ts @@ -30,13 +30,7 @@ export const VaporTeleportImpl = { ? new TeleportFragment('teleport') : new TeleportFragment() - const resolvedProps = new Proxy( - props, - rawPropsProxyHandlers, - ) as any as TeleportProps - let children: Block - renderEffect(() => { frag.updateChildren( (children = slots.default && (slots.default as BlockFn)()), @@ -44,21 +38,28 @@ export const VaporTeleportImpl = { }) renderEffect(() => { - // access the props to trigger tracking - frag.update(extend({}, resolvedProps), children!) + frag.update( + // access the props to trigger tracking + extend( + {}, + new Proxy(props, rawPropsProxyHandlers) as any as TeleportProps, + ), + children!, + ) }) return frag }, } -export class TeleportFragment extends VaporFragment { +class TeleportFragment extends VaporFragment { anchor: Node - targetStart?: Node | null - mainAnchor?: Node - placeholder?: Node - container?: ParentNode | null - currentAnchor?: Node | null + + private targetStart?: Node + private mainAnchor?: Node + private placeholder?: Node + private mountContainer?: ParentNode | null + private mountAnchor?: Node | null constructor(anchorLabel?: string) { super([]) @@ -66,32 +67,37 @@ export class TeleportFragment extends VaporFragment { __DEV__ && anchorLabel ? createComment(anchorLabel) : createTextNode() } - updateChildren(children: Block): void { - const parent = this.anchor.parentNode - if (!parent) return + get currentParent(): ParentNode { + return (this.mountContainer || this.parent)! + } - const container = this.container || parent + get currentAnchor(): Node | null { + return this.mountAnchor || this.anchor + } - // teardown previous - remove(this.nodes, container) + get parent(): ParentNode | null { + return this.anchor.parentNode + } + + updateChildren(children: Block): void { + // not mounted yet, early return + if (!this.parent) return - insert( - (this.nodes = children), - container, - this.currentAnchor || this.anchor, - ) + // teardown previous children + remove(this.nodes, this.currentParent) + + // mount new + insert((this.nodes = children), this.currentParent, this.currentAnchor) } update(props: TeleportProps, children: Block): void { - const parent = this.anchor.parentNode this.nodes = children - const disabled = isTeleportDisabled(props) const mount = (parent: ParentNode, anchor: Node | null) => { insert( this.nodes, - (this.container = parent), - (this.currentAnchor = anchor), + (this.mountContainer = parent), + (this.mountAnchor = anchor), ) } @@ -99,10 +105,10 @@ export class TeleportFragment extends VaporFragment { const target = (this.target = resolveTarget(props, querySelector)) if (target) { if ( - // initial mount - !this.targetStart || + // initial mount into target + !this.targetAnchor || // target changed - this.targetStart.parentNode !== target + this.targetAnchor.parentNode !== target ) { ;[this.targetAnchor, this.targetStart] = prepareAnchor(target) } @@ -110,33 +116,36 @@ export class TeleportFragment extends VaporFragment { mount(target, this.targetAnchor!) } else if (__DEV__) { warn( - `Invalid Teleport target on ${this.targetStart ? 'update' : 'mount'}:`, + `Invalid Teleport target on ${this.targetAnchor ? 'update' : 'mount'}:`, target, `(${typeof target})`, ) } } - if (parent && disabled) { - if (!this.mainAnchor) { - this.mainAnchor = __DEV__ - ? createComment('teleport end') - : createTextNode() - } - if (!this.placeholder) { - this.placeholder = __DEV__ - ? createComment('teleport start') - : createTextNode() - } - if (!this.mainAnchor.isConnected) { - insert(this.placeholder, parent, this.anchor) - insert(this.mainAnchor, parent, this.anchor) - } + // mount into main container + if (isTeleportDisabled(props)) { + if (this.parent) { + if (!this.mainAnchor) { + this.mainAnchor = __DEV__ + ? createComment('teleport end') + : createTextNode() + } + if (!this.placeholder) { + this.placeholder = __DEV__ + ? createComment('teleport start') + : createTextNode() + } + if (!this.mainAnchor.isConnected) { + insert(this.placeholder, this.parent, this.anchor) + insert(this.mainAnchor, this.parent, this.anchor) + } - mount(parent, this.mainAnchor) + mount(this.parent, this.mainAnchor) + } } - - if (!disabled) { + // mount into target container + else { if (isTeleportDeferred(props)) { queuePostFlushCb(mountToTarget) } else { @@ -147,13 +156,12 @@ export class TeleportFragment extends VaporFragment { remove = (parent: ParentNode | undefined): void => { // remove nodes - remove(this.nodes, this.container || parent) + remove(this.nodes, this.currentParent) // remove anchors if (this.targetStart) { - let parentNode = this.targetStart.parentNode! - remove(this.targetStart!, parentNode) - remove(this.targetAnchor!, parentNode) + remove(this.targetStart!, this.target!) + remove(this.targetAnchor!, this.target!) } if (this.placeholder) { remove(this.placeholder!, parent) @@ -167,12 +175,11 @@ export class TeleportFragment extends VaporFragment { } function prepareAnchor(target: ParentNode | null) { - const targetStart = createTextNode('') + const targetStart = createTextNode('') as Text & { [TeleportEndKey]: Node } const targetAnchor = createTextNode('') // attach a special property, so we can skip teleported content in // renderer's nextSibling search - // @ts-expect-error targetStart[TeleportEndKey] = targetAnchor if (target) {