官方文档
视频教程


详细的 teleport 使用步骤
1. 定义要瞬移的内容
使用 <teleport></teleport>
标签包裹内容,且给 to
属性绑定瞬移位置的选择器。
/src/components/HelloWorld.vue
:
<template>
<div class="hello">
<div>Hello World</div>
<teleport to="#modal">
<h1>Hello Modal</h1>
</teleport>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "HelloWorld",
props: {
msg: String
}
});
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
margin: 40px 0 0;
color: #42b983;
}
</style>
2. 引入 HelloWorld 组件,且设定要瞬移后的位置
/src/App.vue
<template>
<div id="app">
<h1>{{ count }}</h1>
<button @click="plus">plus</button>
<br />
<HelloWorld />
<div
id="modal"
style="border: 1px solid #42b983; padding: 20px; margin: 20px 0"
></div>
</div>
</template>
<script lang="ts">
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld
},
setup() {
const count = ref(0);
function plus() {
count.value++;
}
return {
count,
plus
};
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3. 这时候可以看到控制台有warning

4. 将瞬移后的位置改为在 index.html 里
/public/index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- #modal 放在 #app 后 -->
<div
id="modal"
style="border: 1px solid #42b983; padding: 20px; margin: 20px 0"
></div>
<!-- built files will be auto injected -->
</body>
</html>
5. 能正常显示了

6. 加入数据交互
假设就为一个 Modal
:
- 默认为不渲染状态。
- 在
HelloWorld
组件里有一个按钮,点击能渲染显示Modal
-
Modal
内部有一个按钮,点击能关闭Modal
<template>
<div class="hello">
<div>Hello World</div>
<!-- 在 HelloWorld 组件里有一个按钮,点击能渲染显示 Modal -->
<button @click="showModal = true">open modal</button>
<teleport to="#modal">
<!-- showModal 状态来控制是否显示 Modal 内容 -->
<template v-if="showModal">
<h1>Hello Modal</h1>
<!-- Modal 内部有一个按钮,点击能关闭 Modal -->
<button @click="showModal = false">close</button>
</template>
</teleport>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
name: "HelloWorld",
props: {
msg: String
},
setup() {
// showModal 状态来控制是否显示 Modal 内容
const showModal = ref(false);
return {
showModal
};
}
});
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
margin: 40px 0 0;
color: #42b983;
}
</style>

可以观察到:
虽然我们是在 HelloWorld.vue
组件里定义 <teleport to="#modal"></teleport>
内容的,但它实际渲染的位置在 #modal
处,完成了“瞬间移动”。

teleport 上还有一个属性 disabled
设置为 true
:
<template>
<div class="hello">
<div>Hello World</div>
<!-- 在 HelloWorld 组件里有一个按钮,点击能渲染显示 Modal -->
<button @click="showModal = true">open modal</button>
<teleport to="#modal" :disabled="true">
<!-- showModal 状态来控制是否显示 Modal 内容 -->
<template v-if="showModal">
<h1>Hello Modal</h1>
<!-- Modal 内部有一个按钮,点击能关闭 Modal -->
<button @click="showModal = false">close</button>
</template>
</teleport>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
name: "HelloWorld",
props: {
msg: String
},
setup() {
// showModal 状态来控制是否显示 Modal 内容
const showModal = ref(false);
return {
showModal
};
}
});
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
margin: 40px 0 0;
color: #42b983;
}
</style>
查看页面会发现:弹窗内容不在 #modal
即绿色框里

查看 DOM 结构:

网友评论