Vue3 过渡动画与 Teleport:旧项目迁移指南
·
Vue2 的
<transition>、<transition-group>、<keep-alive>我们都很熟。到了 Vue3,API 更强大,还新增了 Teleport(传送门),可以把弹窗、抽屉挂到 body。今天我们用动画+弹窗的案例,教你快速迁移旧项目的过渡逻辑,并掌握 Teleport 的高级用法。
🎯 需求
- 列表项淡入淡出。
- 弹窗从按钮“传送”到 body。
- 多个弹窗共享遮罩,支持滚动穿透控制。
🧱 基础:transition
<template>
<div>
<button @click="show = !show">切换</button>
<Transition name="fade">
<p v-if="show">你好,这是一段测试文字</p>
</Transition>
</div>
</template>
<style scoped>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
- Vue3 里还是用
name+-enter-from/-enter-active写法。 - 想要 JS 钩子:
@before-enter、@after-leave等。
🧠 transition-group
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</TransitionGroup>
- 必须提供唯一 key。
- Vue3 默认使用
v-moveclass 增加移动过渡。 - CSS:
.list-enter-active, .list-leave-active { transition: all 0.3s; } .list-enter-from, .list-leave-to { opacity: 0; transform: translateY(10px); } .list-move { transition: transform 0.3s; }
🚪 Teleport:弹窗传送门
<template>
<Teleport to="body">
<div v-if="visible" class="modal-mask">
<div class="modal">
<slot />
<button @click="$emit('close')">关闭</button>
</div>
</div>
</Teleport>
</template>
to="body"把内容挂到 body。- 适合弹窗、通知、Tooltip。
- 接收多个 Teleport 目标:
<Teleport to="#portal-root">。
🔄 Teleport + Transition 结合
<Teleport to="body">
<Transition name="fade-scale">
<div v-if="visible" class="modal-mask">
<div class="modal">
<slot />
</div>
</div>
</Transition>
</Teleport>
- 传送后仍然保留过渡动画。
- 可使用
appear属性让初次渲染也有动画。
🧰 滚动穿透控制
watch(visible, (val) => {
document.body.style.overflow = val ? 'hidden' : '';
});
onUnmounted(() => {
document.body.style.overflow = '';
});
- Teleport 出去的元素不受父容器限制,所以要手动控制滚动。
🧯 常见坑
| 坑 | 现象 | 解决 |
|---|---|---|
| Teleport 目标不存在 | 控制台警告 | 确保 DOM 中存在对应 selector |
| transition-group 动画乱跳 | 未设置固定高度 | 给列表项定义高度或使用 flex |
| 动画重复触发 | key 重复或丢失 | 确保唯一 key |
| Teleport 内容没继承样式 | 父级作用域样式未作用 | 使用全局样式或 :global() |
🧱 keep-alive 搭配
<KeepAlive include="TabA,TabB">
<component :is="activeTab" />
</KeepAlive>
- 在
<script setup>中使用:<KeepAlive> <component :is="currentView" /> </KeepAlive> - 配合 Teleport 时保持状态:例如 Tab 里的弹窗不丢失内容。
🏁 小练习
- 把项目里的弹窗改用 Teleport,解决遮罩层被父元素遮挡的问题。
- 写一个
useModal组合式函数,控制 Teleport 弹窗的显示/关闭。
下一篇,我们将讨论“构建工具迁移”:Vue3 项目用 Vite 替代 Vue CLI/webpack,需要改哪些配置?怎么处理别名、env、跨域代理?一次说清楚。
更多推荐


所有评论(0)