🌀 今日秘技: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 -->