x-teleport
x-teleport 指令允许你将 Alpine 模板的一部分传送到页面 DOM 的另一个完全不同的位置。
这对于模态框(尤其是嵌套模态框)等场景非常有用,可以突破当前 Alpine 组件的 z-index 层级。
x-teleport
通过将 x-teleport 附加到 <template> 元素上,你告诉 Alpine 将该元素"追加"到提供的选择器所指定的位置。
x-teleport选择器可以是任何你通常传递给document.querySelector的字符串。它将找到第一个匹配的元素,无论是标签名(body)、类名(.my-class)、ID(#my-id)还是任何其他有效的 CSS 选择器。
→ 阅读更多关于 document.querySelector
以下是一个示例性的模态框示例:
<body>
<div x-data="{ open: false }">
<button @click="open = ! open">Toggle Modal</button>
<template x-teleport="body">
<div x-show="open">
Modal contents...
</div>
</template>
</div>
<div>Some other content placed AFTER the modal markup.</div>
...
</body>
请注意,在切换模态框时,实际的模态框内容显示在"Some other content..."元素之后?这是因为当 Alpine 初始化时,它看到 x-teleport="body",并将该元素追加和初始化到提供的元素选择器所指定的位置。
事件转发
Alpine 尽力使传送体验无缝衔接。你通常可以在模板中做的任何操作,都应该能在 x-teleport 模板内部完成。传送后的内容可以访问组件的正常 Alpine 作用域以及其他功能,如 $refs、$root 等。
但是,原生 DOM 事件没有传送的概念,因此,例如,如果你从传送后的元素内部触发了一个"click"事件,该事件将像往常一样沿着 DOM 树向上冒泡。
为了使这种体验更无缝,你可以通过简单地在 <template x-teleport...> 元素本身上注册事件监听器来"转发"事件,如下所示:
<div x-data="{ open: false }">
<button @click="open = ! open">Toggle Modal</button>
<template x-teleport="body" @click="open = false">
<div x-show="open">
Modal contents...
(click to close)
</div>
</template>
</div>
注意,我们现在能够从 <template> 元素外部监听从传送后的元素内部分发的事件?
Alpine 通过查找注册在 <template x-teleport...> 上的事件监听器,并阻止这些事件传播到实际的、已传送的 DOM 元素之外来实现这一点。然后,它创建该事件的一个副本,并从 <template x-teleport...> 重新分发它。
嵌套
如果你尝试在一个模态框内嵌套另一个模态框,传送功能尤其有用。Alpine 使其变得简单:
<div x-data="{ open: false }">
<button @click="open = ! open">Toggle Modal</button>
<template x-teleport="body">
<div x-show="open">
Modal contents...
<div x-data="{ open: false }">
<button @click="open = ! open">Toggle Nested Modal</button>
<template x-teleport="body">
<div x-show="open">
Nested modal contents...
</div>
</template>
</div>
</div>
</template>
</div>
在将两个模态框都切换为"打开"后,虽然它们在代码中是父子嵌套的,但在页面上它们将渲染为同级元素,而不是彼此嵌套。