Skip to content

Teleport

<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

1.组件属性

<Teleport> 组件可接收以下属性

ts
interface TeleportProps {
  /**
   * 必填项。指定目标容器。
   * 可以是选择器或实际元素。
   */
  to: string | HTMLElement
  /**
   * 当值为 `true` 时,内容将保留在其原始位置
   * 而不是移动到目标容器中。
   * 可以动态更改。
   */
  disabled?: boolean
  /**
   * 当值为 `true` 时,Teleport 将推迟
   * 直到应用的其他部分挂载后
   * 再解析其目标。(3.5+)
   */
  defer?: boolean
}

2.基本使用

<Teleport>一个比较好的创建就是我们自己封装Modal弹窗,若在一个组件中使用弹窗,其dom结构一定是跟着组件来的,但是使用<Teleport>我们可以把弹窗组件挂载到body身上

vue
<template>
	<teleport to="body" v-if="show">
		<div class="cover" @click="show = false">
			<div class="modal">
				<slot></slot>
			</div>
		</div>
	</teleport>
</template>
<script setup>
import { ref } from 'vue'
const show = ref(false)
const showModal = () => {
	show.value = true
}
</script>

<style lang="scss">
.cover {
	position: fixed;
	width: 100vw;
	height: 100vh;
	background: rgba(0, 0, 0, 0.2);
	left: 0;
	top: 0;
	display: flex;
	justify-content: center;
	align-items: center;
	z-index: 9999;
	.modal {
		width: 800px;
		height: 500px;
		border-radius: 5px;
		background: #fff;
		padding: 20px;
		box-sizing: border-box;
	}
}
</style>

3.搭配组件使用

<Teleport> 只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。

也就是说,如果 <Teleport> 包含了一个组件,那么该组件始终和这个使用了 <Teleport> 的组件保持逻辑上的父子关系。传入的 props 和触发的事件也会照常工作。

这也意味着来自父组件的注入也会按预期工作,子组件将在 Vue Devtools 中嵌套在父级组件下面,而不是放在实际内容移动到的地方。

4.指定目标容器

to属性可以传入一个HTMLElement,或者一个选择器字符串

vue
<Teleport to="#some-id" />
<Teleport to=".some-class" />
<Teleport to="[data-teleport]" />

5.有条件地禁用

disabled属性可以禁止Teleport将里面的元素穿梭

vue
<Teleport to="#popup" :disabled="displayVideoInline">
  <video src="./my-movie.mp4">
</Teleport>

6.延迟目标解析

在 Vue 3.5 及更高版本中,我们可以使用 defer 属性推迟 Teleport 的目标解析,直到应用的其他部分挂载。这允许 Teleport 将由 Vue 渲染且位于组件树之后部分的容器元素作为目标:

vue
<Teleport defer to="#late-div">...</Teleport>

<!-- 稍后出现于模板中的某处 -->
<div id="late-div"></div>

7.多个Teleport共享目标

一个可重用的模态框组件可能同时存在多个实例。对于此类场景,多个 <Teleport> 组件可以将其内容挂载在同一个目标元素上,而顺序就是简单的顺次追加,后挂载的将排在目标元素下更后面的位置上。

比如下面这样的用例:

html
<Teleport to="#modals">
  <div>A</div>
</Teleport>
<Teleport to="#modals">
  <div>B</div>
</Teleport>

渲染的结果为:

html
<div id="modals">
  <div>A</div>
  <div>B</div>
</div>

MIT Licensed