Vue Teleport 本身不直接管理多弹窗层级,但它为层级叠加提供了必要前提:把弹窗 DOM 移出父级作用域,让 z-index 真正生效;真正的层级叠加管理需配合响应式状态、统一 zIndex 计数器和用户交互逻辑实现。
Vue Teleport 本身不直接管理多弹窗层级,但它为层级叠加提供了必要前提:把弹窗 DOM 移出父级作用域,让 z-index 真正生效。真正的层级叠加管理,需要配合响应式状态 + 统一 zIndex 计数器 + 用户交互逻辑来实现。
所有对话框必须用 Teleport 渲染到同一目标节点(如 body 或专用容器 <div id="dialog-root"></div>),否则不同弹窗可能落在不同 DOM 上下文中,z-index 无法横向比较。
<Teleport to="body">... 和 <Teleport to="#app">... 混用——它们渲染在不同父节点下,z-index 互不感知<div id="dialog-root" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%;"></div>,所有弹窗都传送到这里不能靠静态 class 或固定值,必须为每个弹窗实例分配唯一可变的 z-index,并实时响应变化。
const dialogZIndices = reactive<Record<string, number>>({})
Symbol() 或时间戳 + 随机数),并设其 zIndex 为当前最大值 + 1<div class="dialog-wrapper" :style="{ zIndex: dialogZIndices[id] }">
用户操作是层级变化的核心驱动力,需同时支持两种场景:
bringToFront(id) 函数:遍历 dialogZIndices 找出最大值,将当前 id 的 zIndex 设为该值 + 1bringToFront(newId),确保它默认在最上层nextTick 或简单计时器控制更新节奏遮罩(overlay)不是装饰,而是层级体系的一部分。它必须和对应弹窗保持严格层级关系:
zIndex - 1),避免遮罩盖住其他弹窗的标题栏