Teleport简介
<Teleport> 是一个内置的 Vue 组件,它具备将组件内部特定的模板内容“投射”或“传输”至该组件 DOM 结构外部指定位置的功能。这一特性使得开发者能够灵活地调整页面元素的布局和嵌套关系,从而实现更高级的界面设计和交互效果。<简单地来说就像游戏中的传送门>
使用场景
有时我们需要一个组件的部分内容(如全屏模态框)在逻辑上属于该组件,但在 DOM 结构上却需要被渲染到整个 Vue 应用的其他地方,甚至是应用的根节点之外。
这种情况通常出现在需要全屏覆盖的模态框(Modal)或对话框(Dialog)等组件中。从逻辑上看,模态框的触发按钮和模态框本身都是同一个组件的一部分,因为它们的状态(如显示或隐藏)通常是相互关联的。但是,如果我们将整个组件(包括触发按钮和模态框)一起渲染,那么模态框很可能会被嵌套在 DOM 结构的深层位置。
这样的嵌套位置可能会给 CSS 布局带来困难。例如,全屏模态框通常需要覆盖整个页面,包括页面的头部和底部。如果模态框被嵌套在深层 DOM 结构中,那么使用 CSS 来实现全屏覆盖可能会变得非常棘手,甚至需要用到一些复杂的选择器或 CSS 技巧。
因此,Vue 的 <Teleport>
组件提供了一种解决方案。通过 <Teleport>
,我们可以将组件内部的模板内容“传送”到 DOM 结构的其他位置,甚至是根节点之外。这样,我们就可以保持组件的逻辑完整性,同时实现更好的 CSS 布局和用户体验。
未使用<Teleport>
组件的代码:
<script setup>
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<button @click="open = true">Open Modal</button>
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</template>
<style scoped>
.modal {
position: fixed;
z-index: 999;
top: 20%;
left: 50%;
width: 300px;
margin-left: -150px;
}
</style>
使用<Teleport>
组件后:
<template>
<button @click="open = true">Open Modal</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</Teleport>
</template>
<Teleport>
它允许你将组件内部的模板内容“传送”到组件 DOM 结构外部的一个特定位置。这是通过 to
属性来实现的。
to
属性有两个可能的值:
-
CSS 选择器字符串:你可以提供一个 CSS 选择器字符串,用来匹配 DOM 树中的某个元素。
<Teleport>
会将内容传送到第一个匹配该选择器的元素内部。 -
DOM 元素对象:你也可以直接提供一个 DOM 元素对象,
这段代码的作用就是告诉 Vue把以下模板片段传送到 body 标签下。<Teleport>
会直接将内容传送到这个元素内部。
<Teleport>
只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。也就是说,如果 <Teleport>
包含了一个组件,那么该组件始终和这个使用了 <teleport>
的组件保持逻辑上的父子关系。传入的 props 和触发的事件也会照常工作。