首页 > 编程笔记 > JavaScript笔记
阅读:6
Vue Teleport组件的用法(附带实例)
Teleport 中文翻译为“瞬间移动”,顾名思义,Teleport 内置组件可以将组件中的一部分元素移动到指定的目标元素上。
Vue 项目中的所有组件都被包含在 App 这一根组件下,而在入口文件 main.js 中引入根组件 App 后会将其挂载于“#app”网页元素上,这就意味着 Vue 项目中的所有组件元素都被包含在“#app”网页元素中。
假如现在有一个需求,在网页的顶层显示一个模态框。如果可以实现模态框元素直接包含在 body 标签中,让该元素和“#app”网页元素同级并列,那么控制结果会变得简单,此时就可以使用具有移动功能的内置组件 Teleport 来实现。
下面就来实现这个需求,在 App 组件中引入一个具有弹出框的子组件 GlobalAlert,App.vue 文件代码如下:
此时 components/GlobalAlert.vue 文件代码如下:

图 1 页面效果
点击“打开模态框”按钮,会发现在页面顶层显示了一个模态框。利用 Vue 开发者调试工具中的 Elements 审查元素,可以确认“#app”网页元素和模态框元素是并列关系,模态框的 div 处于页面顶层 body 下,如下图所示:

图 2 “#app”网页元素和模态框元素并列
从图 1 中可以观察到,还有一个“非禁用移动功能”按钮,同样从代码中可以看到 disabled 属性的相关实现。disabled 属性可以确认是否禁用移动功能,如果 disabled 属性值为 true,则移动功能被禁用,反之可以使用。在禁用状态下,Teleport 组件内的元素仍旧保持不移动状态的元素位置。
点击“非禁用移动功能”按钮后,观察控制台可以发现模态框的 div 被包含在“#app”网页元素下,如下图所示:

图 3 模态框的div被包含在“#app”网页元素下
Vue 项目中的所有组件都被包含在 App 这一根组件下,而在入口文件 main.js 中引入根组件 App 后会将其挂载于“#app”网页元素上,这就意味着 Vue 项目中的所有组件元素都被包含在“#app”网页元素中。
假如现在有一个需求,在网页的顶层显示一个模态框。如果可以实现模态框元素直接包含在 body 标签中,让该元素和“#app”网页元素同级并列,那么控制结果会变得简单,此时就可以使用具有移动功能的内置组件 Teleport 来实现。
下面就来实现这个需求,在 App 组件中引入一个具有弹出框的子组件 GlobalAlert,App.vue 文件代码如下:
<template> <GlobalAlert /> </template> <script setup> import GlobalAlert from './components/GlobalAlert.vue'; </script> <style> #app { text-align: center; background: #2c3e50; padding-top: 60px; height: 100vh; } </style>子组件 GlobalAlert 上需要有两个功能按钮和一个模态框。按钮用于切换功能,需要显示在页面上,因此会被包含在“#app”网页元素中。而带有动画效果的模态框则与“#app”同级并列,这样更容易控制其出现在页面的顶层。可以通过在瞬间移动组件 Teleport 中将 to 属性值设置为“body”来实现效果。
此时 components/GlobalAlert.vue 文件代码如下:
<script setup> import { ref } from 'vue'; const isOpen = ref(false); // 控制是否显示模态框 const isTeleport = ref(false); // 控制是否禁用 Teleport 组件 </script> <template> <!-- 按钮部分将被嵌套于“#app”网页元素中 --> <button @click="isOpen = !isOpen"> {{ isOpen ? '关闭' : '打开' }}模态框 </button> <button @click="isTeleport = !isTeleport"> {{ isTeleport ? '禁用' : '非禁用' }}移动功能 </button> <!-- 利用Teleport 内置组件将其包含的元素移动到 body 标签内 --> <Teleport to="body" :disabled="isTeleport"> <!-- 动画效果增强视觉 --> <Transition mode="in-out"> <!-- 利用 v-if 指令控制模态框的显示与隐藏 --> <div v-if="isOpen" class="modal"> <p>元素被移动到 body 标签内,与 “#app” 网页元素是并列关系</p> <!-- 按钮点击事件控制模态框的隐藏与显示 --> <button class="close" type="button" @click="isOpen = false"> 关闭 </button> </div> </Teleport> </transition> </template> <style scoped> .modal { position: fixed; isolation: isolate; z-index: 1; top: 2rem; left: 2rem; width: 20rem; border: 1px solid grey; padding: 0.5rem; border-radius: 1rem; background-color: grey; box-shadow: 2px 2px 4px grey; backdrop-filter: blur(4px); color: #f4f4f4; } button { padding: 0.5rem; border: 0; border-radius: 1rem; box-shadow: inset 0 -1px 4px grey, 1px 1px 2px grey; cursor: pointer; transition: box-shadow 0.15s ease-in-out; } button:hover { box-shadow: inset 0 -1px 2px grey, 1px 1px 2px grey; } .close { display: block; margin-left: auto; } /* 在没有设置 name 时可以设置统一的动画样式类名,以 v-xxx 方式命名 */ .v-enter-active, .v-leave-active { transition: all 0.25s ease-in-out; } .v-enter-from, .v-leave-to { opacity: 0; transform: translateX(-10vw); } </style>运行代码,页面效果如下图所示:

图 1 页面效果
点击“打开模态框”按钮,会发现在页面顶层显示了一个模态框。利用 Vue 开发者调试工具中的 Elements 审查元素,可以确认“#app”网页元素和模态框元素是并列关系,模态框的 div 处于页面顶层 body 下,如下图所示:

图 2 “#app”网页元素和模态框元素并列
从图 1 中可以观察到,还有一个“非禁用移动功能”按钮,同样从代码中可以看到 disabled 属性的相关实现。disabled 属性可以确认是否禁用移动功能,如果 disabled 属性值为 true,则移动功能被禁用,反之可以使用。在禁用状态下,Teleport 组件内的元素仍旧保持不移动状态的元素位置。
点击“非禁用移动功能”按钮后,观察控制台可以发现模态框的 div 被包含在“#app”网页元素下,如下图所示:

图 3 模态框的div被包含在“#app”网页元素下