文章目录前言一、基本用法1.1 为什么需要 Teleport1.2 Teleport 解决二、to 属性2.1 指定目标位置2.2 挂载点准备2.3 disabled 动态控制三、典型场景3.1 Modal 对话框3.2 Toast 全局通知3.3 全屏 Loading3.4 Dropdown 下拉菜单四、逻辑归属与事件冒泡4.1 组件树 vs DOM 树4.2 事件冒泡遵循组件树4.3 多个 Teleport 到同一目标五、SSR 行为5.1 默认原位渲染5.2 处理方案六、面试聚焦6.1 事件冒泡遵循组件树6.2 Teleport 在 SSR 时的行为6.3 Teleport 解决了什么问题七、易混淆点八、思考与练习总结前言Teleport是 Vue 3 内置组件可将子元素的 DOM 传送到页面其他位置突破父容器的 CSS 限制。本篇会讲清楚Teleport 的基本用法与to属性Modal、Toast、Loading 等典型场景逻辑归属与事件冒泡规则SSR 下的行为一、基本用法1.1 为什么需要 Teleport!-- 问题Modal 嵌套在组件内可能被父容器裁切 -- div classpage styleoverflow: hidden; position: relative; button clickopen true打开弹窗/button div v-ifopen classmodal !-- z-index 可能失效 -- 弹窗内容 /div /div父容器的overflow: hidden、transform、z-index等会限制子元素显示。Modal 需要渲染到body下才能全屏覆盖。1.2 Teleport 解决template button clickopen true打开弹窗/button Teleport tobody div v-ifopen classmodal-mask div classmodal-content p弹窗内容/p button clickopen false关闭/button /div /div /Teleport /template script setup import { ref } from vue const open ref(false) /script style .modal-mask { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 9999; } /styleDOM 渲染到body末尾但组件的 props、emit、生命周期仍属于父组件。二、to 属性2.1 指定目标位置!-- 传送到 body -- Teleport tobody.../Teleport !-- 传送到指定 id -- Teleport to#modal-root.../Teleport !-- 传送到 class -- Teleport to.app-container.../Teleportto接受 CSS 选择器字符串目标元素必须已存在于 DOM 中。2.2 挂载点准备!-- index.html --bodydividapp/divdividmodal-root/div!-- 可选专用挂载点 --/bodyTeleport to#modal-root Modal v-ifvisible / /Teleport2.3 disabled 动态控制Teleport tobody :disabledisMobile Modal / /Teleportdisabled为true时内容渲染在 Teleport 原位不传送SSR 或移动端回退时常用。三、典型场景3.1 Modal 对话框!-- components/Modal.vue -- template Teleport tobody Transition namefade div v-ifmodelValue classmodal-mask click.selfclose div classmodal-box slot / button clickclose关闭/button /div /div /Transition /Teleport /template script setup defineProps({ modelValue: Boolean }) const emit defineEmits([update:modelValue]) const close () emit(update:modelValue, false) /script配合Transition实现淡入淡出Teleport 确保遮罩覆盖全屏。3.2 Toast 全局通知!-- components/Toast.vue -- template Teleport tobody div classtoast-container TransitionGroup nametoast div v-formsg in messages :keymsg.id classtoast-item {{ msg.text }} /div /TransitionGroup /div /Teleport /template style .toast-container { position: fixed; top: 20px; right: 20px; z-index: 10000; } /styleToast 固定在视口右上角不受页面滚动和父容器影响。3.3 全屏 Loadingtemplate Teleport tobody div v-ifloading classloading-mask div classspinner加载中.../div /div /Teleport /template style .loading-mask { position: fixed; inset: 0; background: rgba(255, 255, 255, 0.8); display: flex; align-items: center; justify-content: center; z-index: 99999; } /style3.4 Dropdown 下拉菜单template div classdropdown-trigger clickopen !open 选择项 /div Teleport tobody div v-ifopen classdropdown-menu :style{ top: menuTop px, left: menuLeft px } div v-foritem in options :keyitem{{ item }}/div /div /Teleport /template下拉菜单传送到 body避免被overflow: auto的表格或侧边栏裁切。四、逻辑归属与事件冒泡4.1 组件树 vs DOM 树Vue 组件树App → Page → Modal逻辑父子 DOM 树 body → div#app → ... ; body → div.modalTeleport 渲染位置Teleport只改变 DOM 位置不改变 Vue 组件树props / emit 仍走父组件生命周期仍属于定义 Teleport 的组件父组件可通过v-if控制 Teleport 内容4.2 事件冒泡遵循组件树!-- Parent.vue -- template div clickhandleParentClick Child / /div /template !-- Child.vue -- template Teleport tobody button clickhandleClick按钮/button /Teleport /template点击 Teleport 内的按钮click在 Child 组件内触发 → 沿Vue 组件树向 Parent 冒泡不会冒泡到 DOM 中 Teleport 的实际父元素如 body4.3 多个 Teleport 到同一目标Teleport to#modal-root ModalA v-ifshowA / /Teleport Teleport to#modal-root ModalB v-ifshowB / /Teleport多个 Teleport 传送到同一容器时按声明顺序追加到目标内。五、SSR 行为5.1 默认原位渲染服务端渲染时Teleport默认不传送内容渲染在组件原位 DOM 中。客户端 hydration 完成后才传送到to目标可能造成短暂闪烁。5.2 处理方案!-- 方案一SSR 时禁用 Teleport -- Teleport tobody :disabled!isClient Modal / /Teleport script setup import { ref, onMounted } from vue const isClient ref(false) onMounted(() { isClient.value true }) /script// 方案二Nuxt 等框架内置 SSR Teleport 支持// 需在服务端提供 #teleports 挂载点生产环境使用 Nuxt 等 SSR 框架时按框架文档配置 Teleport 挂载点。六、面试聚焦6.1 事件冒泡遵循组件树Teleport 只移动 DOM不改变 Vue 组件树。事件仍按组件父子关系冒泡不会冒泡到 DOM 中的实际父元素。6.2 Teleport 在 SSR 时的行为默认在原位渲染不传送。客户端激活后才移动到目标位置。可通过disabled或框架配置处理。6.3 Teleport 解决了什么问题Modal、Toast 等需要全屏/固定定位的 UI避免被父容器overflow、z-index、transform裁切或遮挡。七、易混淆点只改 DOM 不改组件树props/emit/生命周期仍属原组件。事件不沿 DOM 冒泡沿 Vue 组件树冒泡。to 目标必须存在挂载前 DOM 中需有对应元素。SSR 默认不传送hydration 后才移动注意闪烁问题。与 Portal 类似React Portal 概念相同Vue 3 内置为 Teleport。八、思考与练习1.Teleport 的作用是什么解析将子元素 DOM 传送到页面其他位置如 body突破父容器 CSS 限制逻辑仍属原组件。2.Modal 为什么常用 Teleport 到 body解析避免被父容器 overflow、z-index、transform 裁切确保遮罩全屏覆盖。3.Teleport 内点击事件如何冒泡解析遵循 Vue 组件树冒泡不遵循 DOM 树。事件向定义 Teleport 的组件的父级传递。4.SSR 时 Teleport 的行为解析默认在原位渲染客户端 hydration 后才传送到 to 目标。5.disabled 属性有什么用解析为 true 时不传送内容渲染在原位。SSR 回退或条件禁用传送时使用。总结TeleportVue 3 内置将 DOM 传送到指定位置逻辑仍属原组件toCSS 选择器指定目标body、#id、.class典型场景Modal、Toast、Loading、Dropdown事件冒泡遵循组件树不遵循 DOM 树SSR默认原位渲染需注意 hydration 闪烁