瀏覽代碼

:bug: Cleans teleported clone (#4328)

* :test_tube: Adds failing test for teleport cleanup

* :bug: Cleans up Teleport clones
Eric Kwoka 9 月之前
父節點
當前提交
ab743bc566

+ 7 - 2
packages/alpinejs/src/directives/x-teleport.js

@@ -1,6 +1,6 @@
 import { skipDuringClone } from "../clone"
 import { directive } from "../directives"
-import { initTree } from "../lifecycle"
+import { initTree, destroyTree } from "../lifecycle"
 import { mutateDom } from "../mutation"
 import { addScopeToNode } from "../scope"
 import { warn } from "../utils/warn"
@@ -64,7 +64,12 @@ directive('teleport', (el, { modifiers, expression }, { cleanup }) => {
         })
     }
 
-    cleanup(() => clone.remove())
+    cleanup(() =>
+      mutateDom(() => {
+        clone.remove()
+        destroyTree(clone)
+      })
+    )
 })
 
 let teleportContainerDuringClone = document.createElement('div')

+ 31 - 0
tests/cypress/integration/directives/x-teleport.spec.js

@@ -122,6 +122,37 @@ test('removing teleport source removes teleported target',
     },
 )
 
+test(
+    'immediately cleans up the clone when the original template is removed',
+    [
+        html`
+            <div x-data="{ show: true, shown: 'original' }">
+                <span x-text="shown"></span>
+                <template x-if="show">
+                    <div>
+                    <template x-teleport="#target">
+                        <button x-data="{ 
+                            init() { this.shown = 'cloned' }, 
+                            destroy() { this.shown = 'destroyed' }
+                        }" @click="show = false">remove</button>
+                    </template>
+                    </div>
+                </template>
+                <section id="target"></section>
+            </div>
+        `,
+    ],
+    ({ get }) => {
+        get('section').should(haveText('remove'));
+        get("button").should(exist());
+        get('span').should(haveText('cloned'));
+        get('button').click();
+        get('section').should(haveText(''));
+        get('button').should(notExist());
+        get('span').should(haveText('destroyed'));
+    }
+);
+
 test('$refs inside teleport can be accessed outside',
     [html`
         <div x-data="{ count: 1 }" id="a">