Vue3 Teleport 應用
Oct 20, 2023 Max Lee
- 父子元件的層級不會受影響
- 資料會 keep alive
Component Props
interface TeleportProps {
to: string | RendererElement | null | undefined;
disabled?: boolean;
}
Use Case
# 避開父層的樣式影響
因為 position: fixed
與 transform
、perspective
、filter
衝突。將 Modal 移至 body 底下可以避開這樣的樣式衝突。
<template>
<button @click="open = true">Open Modal</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</Teleport>
</template>
<style scoped>
.modal {
position: fixed;
z-index: 999;
top: 20%;
left: 50%;
width: 300px;
margin-left: -150px;
}
</style>
# FB & YT 的迷你浮動播放器
# 共用的 Layout 區塊 & 共用的 Modal / Toast
減少「重複的功能實踐」、「重複的元件使用」或「分散的設定」
Layout.vue
<template>
<div class="root">
<header></header>
<main>
<aside></aside>
<section>
<div class="view-header">
<h2 id="view-header__title"></h2>
<p id="view-header__subtitle"></p>
<div id="view-header__extra"></div>
</div>
<router-view></router-view>
</section>
</main>
<footer></footer>
<div v-if="currentModalContent" class="modal">
<p id="modal__content"></p>
<button @click="open = false">Close</button>
</div>
</div>
</template>
<script setup>
// some logic for view-header
// maybe show/hide, dynamic width/height, event handler....
const currentModalContent = ref("")
provide("modal", {
current: readonly(currentModalContent),
set: (id) => currentModalContent.value = id,
remove: () => currentModalContent.value = ""
})
</script>
SomeRouterPage.vue
<template>
<div class="route-1">
<Teleport to="#view-header__title">{{ viewTitle }}</Teleport>
<Teleport to="#view-header__subtitle">{{ viewSubtitle }}</Teleport>
<Teleport to="#view-header__extra">
<button>Click Me</button>
</Teleport>
<section>
<div>.....</div>
</section>
<Teleport v-if="current === A" to="#modal__content">
{{ modalContentA }}
</Teleport>
<Teleport v-if="current === B" to="#modal__content">
{{ modalContentB }}
</Teleport>
</div>
</template>
<script setup>
const { current, set, remove } = inject("modal")
</script>