Vue2依赖第三方库portal-vue实现传送门,存在体积大、SSR配置繁琐、调试困难等痛点。Vue3内置Teleport组件,原生支持多源合并、条件禁用、SSR,不引入额外DOM包裹,优化了开发体验。迁移时需将portal-vue的成对组件改为Teleport的to直接指向目标DOM节点。
在 Vue 组件树中,子组件的 DOM 默认被限制在父组件内部。但许多场景要求将内容“搬”到组件树之外的某个 DOM 节点渲染——例如模态框、对话框,它们需要 position: fixed,却容易受父级 overflow:hidden、transform 或 z-index 干扰。再比如 Toast 通知、全局提示、浮层菜单、下拉、Tooltip,甚至跨布局区域的内容注入(将某块内容“投递”到页脚插槽)。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
这类需求的核心逻辑非常明确:逻辑仍归属于原组件,但渲染位置需要脱离原组件树——这就是“传送门(Portal)模式”。
Vue2 官方未提供内置传送门,社区事实标准是 portal-vue 库(v2 适配 Vue2)。它提供一对配合使用的组件:
| 组件 | 作用 |
|---|---|
| 发送端,将包裹的内容“投递”到指定目标 |
| 接收端,在自身位置渲染收到的内容 |
我是被传送到外部的弹窗
与 通过同名字符串匹配, 处即渲染内容。
| 属性 | 说明 |
|---|---|
name | 目标名称,必须全局唯一(除非开启 multiple) |
multiple | 允许多个 portal 同时投递到同一 target,内容按顺序拼接 |
slim | 为 true 时不渲染额外的 wrapper 元素,直接用 slot 的单一根节点 |
tag | 指定 wrapper 渲染的标签(默认 div),可设为空字符串配合 slim |
order | 多个 portal 投递时的排序权重 |
slotProps / slotTag | 当 source 用 scoped slot 时的透传配置 |
默认情况下,一个 target 只能接收最后一个 portal 的内容(后到的覆盖先到的),要接收多个必须显式开启 multiple:
portal-vue 体积不小,且需随 Vue2 版本严格匹配(v2 库对应 Vue2,v3 库对应 Vue3),升级成本高。SSRegress 等机制),配置繁琐、易踩坑。portal-target 默认套一层 ,破坏预期样式(需 slim 规避),且多个 portal 时 DOM 结构不够直观。
- 单根限制:Vue2 模板要求单一根节点,配合传送时编写复杂内容不够灵活。
- 响应式/重渲染逻辑隐式:portal 内容的更新依赖库的订阅机制,偶发“内容不刷新”需排查 target 注册时机。
三、Vue3 方案:内置
Vue3 官方内置 组件,直接将“传送门”作为一等公民纳入框架,从根本上解决了上述痛点。
1. 基本用法
我会被直接渲染到
下
to 可以是任意 CSS 选择器(如 "#modal-root"、"body"、".some-class"),也可以是一个真实的 HTMLElement。
2. Vue3 的针对性优化点
优化维度 Vue2 portal-vue Vue3 Teleport 是否内置 第三方库,独立维护 框架原生,零额外依赖 多源合并 需要 multiple 显式开启 天然支持,多个 自动顺序追加 条件禁用 portal 侧无内建 disabled(v3 库才有) 内建 :disabled 属性,为 true 时内容留在原地渲染 SSR 需额外配置 SSRegress 官方内建 SSR 支持,无需 hack 调试 跨树割裂,需手动找 target DevTools 中保持逻辑父子关系,来源清晰 wrapper portal-target 默认包一层 div不引入任何额外 DOM 包裹 根节点限制 受 Vue2 单根约束 Vue3 Fragment 支持,内容可多根 体积/性能 库级运行时开销 编译期优化,运行时极轻
3. 进阶能力
defer(Vue 3.1+):延迟到组件挂载后再查找目标元素,解决“目标节点在初始渲染时尚未存在”的问题(典型场景:目标由其他异步组件动态创建)。
目标还没出现,挂载后再搬过去
多 Teleport 同名合并:多个 不会相互覆盖,而是依次成为 body 的子节点,等价于 portal-vue 开启 multiple,但无需任何配置。
禁用传送保留原位渲染:
...
四、迁移建议(Vue2 → Vue3)
- 卸载
portal-vue,移除所有 / 。
- 发送端改写:
→ (注意 to 仍是名称字符串,但表示选择器,建议改成真实 DOM 选择器如 #x 更直观)。
- 接收端删除:
不再需要—— 直接把内容渲染到 to 指向的 DOM 节点,无需显式声明 target 占位。
- 多源场景:原来靠
multiple 拼接的,直接写多个 即可,删除 multiple。
- 条件渲染:原先靠动态
to 或销毁 portal 来“留在原地”的逻辑,改用 :disabled。
- SSR 项目:移除
SSRegress 相关配置,Teleport 已原生支持。
- slim/wrapper 清理:原来为了消除包裹
div 的 slim 配置可删除,Teleport 本身不引入包裹节点。
迁移对照表
hi
hi
五、一句话总结
从 Vue2 的 portal-vue 到 Vue3 内置的 ,不只是换了个名字,而是从“第三方补丁”进化到“框架原生能力”。迁移时去掉发送端、接收端成对组件,改用 Teleport to 直接指向目标 DOM 节点,再配合 disabled、defer 等内建特性,整个传送门体验终于变得清爽、可控、无副作用。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述