2
0
Эх сурвалжийг харах

fix(runtime-vapor): reuse teleport anchors when keyed roots reorder (#14591)

edison 3 сар өмнө
parent
commit
df8e1eb0b6

+ 35 - 0
packages/runtime-vapor/__tests__/components/Teleport.spec.ts

@@ -9,6 +9,7 @@ import {
   VaporTeleport,
   VaporTransition,
   child,
+  createFor,
   createIf,
   createTemplateRefSetter,
   createVaporApp,
@@ -1411,3 +1412,37 @@ test('should clean up old anchors when target changes', async () => {
   // New target should have the content
   expect(targetB.childNodes.length).toBe(oldChildCount)
 })
+
+test('should not duplicate main-view anchors when keyed list reorders teleport roots', async () => {
+  const target = document.createElement('div')
+  const items = ref([
+    { id: 'one', text: 'one' },
+    { id: 'two', text: 'two' },
+  ])
+
+  const { host } = define(() =>
+    createFor(
+      () => items.value,
+      item =>
+        createComponent(
+          VaporTeleport,
+          { to: () => target },
+          { default: () => template(item.value.text)() },
+        ),
+      item => item.id,
+    ),
+  ).render()
+
+  const countAnchors = (label: 'start' | 'end') =>
+    (host.innerHTML.match(new RegExp(`<!--teleport ${label}-->`, 'g')) || [])
+      .length
+
+  expect(countAnchors('start')).toBe(2)
+  expect(countAnchors('end')).toBe(2)
+
+  items.value = [items.value[1], items.value[0]]
+  await nextTick()
+
+  expect(countAnchors('start')).toBe(2)
+  expect(countAnchors('end')).toBe(2)
+})

+ 9 - 5
packages/runtime-vapor/src/components/Teleport.ts

@@ -256,10 +256,14 @@ export class TeleportFragment extends VaporFragment {
   insert = (container: ParentNode, anchor: Node | null): void => {
     if (isHydrating) return
 
-    // insert anchors in the main view
-    this.placeholder = __DEV__
-      ? createComment('teleport start')
-      : createTextNode()
+    // Re-inserting an already-mounted teleport should move existing anchors
+    // instead of creating a second placeholder in the main view.
+    if (!this.placeholder) {
+      this.placeholder = __DEV__
+        ? createComment('teleport start')
+        : createTextNode()
+    }
+
     insert(this.placeholder, container, anchor)
     insert(this.anchor!, container, anchor)
     this.handlePropsUpdate()
@@ -276,7 +280,7 @@ export class TeleportFragment extends VaporFragment {
 
     // remove anchors
     if (this.targetStart) {
-      remove(this.targetStart!, this.target!)
+      remove(this.targetStart, this.target!)
       this.targetStart = undefined
       remove(this.targetAnchor!, this.target!)
       this.targetAnchor = undefined