定义和使用
Vue鼓励我们通过将UI和相关行为封装到组件中来构建UI。我们可以将它们彼此嵌套以构建一棵构成应用程序UI的树。
但是,有时组件模板的一部分在逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移到DOM中Vue应用程序外部的DOM中的其他位置。
常见的情况是创建一个包含全屏模式的组件。在大多数情况下,您希望模态的逻辑存在于组件中,但是模态的定位很快很难通过CSS来解决,或者需要更改组件的组成。
考虑以下HTML结构。
<body>
<div style="position: relative;">
<h3>Tooltips with Vue 3 Teleport</h3>
<div>
<modal-button></modal-button>
</div>
</div>
</body>
让我们来看看 modal-button。
该组件将具有一个 button 触发模态打开的 div 元素,以及一个带有的类的元素,该类 .modal 将包含模态的内容和一个用于自动关闭的按钮。
const app = Vue.createApp({});
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal!
</button>
<div v-if="modalOpen" class="modal">
<div>
I'm a modal!
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
`,
data() {
return {
modalOpen: false
}
}
})
当使用初始 HTML 结构内该组件,我们可以看到一个问题-模态正在呈现内的深度嵌套 div 和 position: absolute 模态的花费相对定位父 div 作为参考。
Teleport 提供了一种干净的方法,使我们可以控制要在 DOM 中哪个父对象下呈现 HTML,而不必求助于全局状态或将其拆分为两个部分。
让我们修改 modal-button 使用 <teleport> 并告诉 Vue 将这个 HTML 传送到 “body” 标签。
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})
尝试一下