跳转至

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 placed AFTER the modal markup.

请注意,在切换模态框时,实际的模态框内容显示在"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>

在将两个模态框都切换为"打开"后,虽然它们在代码中是父子嵌套的,但在页面上它们将渲染为同级元素,而不是彼此嵌套。