🌀 今日秘技:Teleport 与 Suspense の时空魔法
1. Teleport 任意门
<template> <!-- 🚪 将组件传送到 body 末尾 --> <Teleport to="body"> <div class="modal"> <h2>重要通知!🎉</h2> <button @click="close">关闭</button> </div> </Teleport> <!-- 🪐 传送到自定义容器 --> <Teleport :to="isMobile ? '#mobile-menu' : '#desktop-menu'"> <NavBar /> </Teleport>
</template> <script setup>
// 动态控制传送位置
const isMobile = useMediaQuery('(max-width: 768px)')
</script> <style scoped>
.modal { position: fixed; z-index: 999; /* 样式不再受父组件影响! */
}
</style>
🔔 核心场景:
- 模态框/通知栏全局展示
- 跨布局层级组件渲染
- 响应式动态切换渲染位置
2. Suspense 悬念结界
<template> <!-- 🛡️ 异步组件加载结界 --> <Suspense> <template #default> <AsyncDashboard /> </template> <template #fallback> <div class="skeleton-loader">🌀 加载中...</div> </template> </Suspense> <!-- 🔥 多异步依赖管理 --> <Suspense :timeout="3000"> <template #default> <ArticleContent :id="articleId" /> <CommentList :id="articleId" /> </template> </Suspense>
</template> <script setup>
// 异步组件定义
const AsyncDashboard = defineAsyncComponent(() => import('./Dashboard.vue').then(comp => { // 模拟网络延迟 return new Promise(resolve => setTimeout(() => resolve(comp), 1500) ) })
)
</script>
🔔 高阶技巧:
- 配合
defineAsyncComponent
实现代码分割 - 通过
timeout
属性设置加载超时 - 嵌套使用管理复杂异步依赖链
❄️ 冷知识:Suspense の心跳检测
// 监听异步状态变化
import { onServerPrefetch } from 'vue' // 服务端数据预取
onServerPrefetch(async () => { await fetchData()
}) // 客户端心跳检测
const { isPending } = useSuspense()
watch(isPending, (loading) => { console.log(loading ? '🌀 数据加载中...' : '✨ 数据就绪!')
})
🌟 实验室时空装置
实现智能错误边界
<template> <Suspense @resolve="logSuccess" @fallback="logLoading" @pending="logPending"> <ErrorBoundary> <AsyncComponent /> </ErrorBoundary> </Suspense>
</template> <script setup>
const logSuccess = () => console.log('✅ 数据加载成功')
const logLoading = () => console.log('⏳ 进入加载状态')
const logPending = () => console.log('🔄 等待异步依赖') // 错误边界组件
const ErrorBoundary = { setup(_, { slots }) { const error = ref(null) const handleError = (err) => { error.value = err console.error('🔥 组件崩溃:', err) } return () => { return error.value ? h('div', '😱 紧急修复界面') : slots.default?.() } }
}
</script>
明日秘典:《VueUse 魔法道具库——30个提升效率の神器》 🧰
(留言告诉我你最想拥有的 Vue 超能力,本魔导师为你定制代码咒语!🔮)
🛎️ 本日避坑指南:
- Teleport 的 CSS 陷阱
/* ❌ 父组件的样式可能污染传送内容 */
.parent-class .modal { /* 失效!因为 modal 已被传送到外层 */
} /* ✅ 始终使用 scoped 样式或全局样式 */
.modal { /* 全局样式 */ }
:deep(.modal) { /* scoped 穿透 */ }
- Suspense 的 SSR 限制
// ❌ 服务端渲染时无法显示 fallback
// ✅ 需在服务端预先加载数据
export async function serverPrefetch() { await store.dispatch('fetchData')
}
- 异步组件缓存策略
// 🚀 配置加载缓存
const AsyncComp = defineAsyncComponent({ loader: () => import('./HeavyComponent.vue'), delay: 200, // 延迟显示 loading timeout: 3000, // 超时时间 suspensible: false // 禁用 Suspense 控制
})
- 多层 Teleport 优先级
<!-- 后写的 Teleport 会覆盖先写的 -->
<Teleport to="#target">内容A</Teleport>
<Teleport to="#target">内容B</Teleport>
<!-- 最终显示内容B -->