]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: save
authordaiwei <daiwei521@126.com>
Fri, 21 Mar 2025 13:53:35 +0000 (21:53 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 21 Mar 2025 13:54:32 +0000 (21:54 +0800)
packages/runtime-vapor/src/components/Teleport.ts

index 4b029b641218f63f81d5c81f7846d764404bcd48..823f6c5cca2d9a910ccde62c00a7e40aaf45ed47 100644 (file)
@@ -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) {