vue3 使用了 composition api 方式来开发,通过查阅文档发现了 vue3 内置了一个 <Teleport>
组件,那么这个组件是什么?有什么用呢,我们如何用 Teleport
组件来封装一个弹窗组件,下面将来一一揭秘。
Teleport 功能介绍
Teleport
是 vue3 提供的一个内置组件,可以将这个组件内部的模板插入到组件外部的制定 DOM 结构上去。
Teleport
使用场景最常见的就是平时封装的模态弹窗组件,封装过模态窗组件的人都知道,弹窗需要全屏,如果在组件内部的 DOM 里面,通过 fixed 布局,会无法覆盖全屏,实在头疼。
使用 Teleport
就可以在组件内部控制组件的状态逻辑,又可以随意插入到组件外部的 DOM 里面去。
Teleport 使用
我们现在来封装一个 Modal 组件,代码如下
<script>
export default {
data() {
return {
open: false,
};
},
};
</script>
<template>
<button @click="open = true">打开</button>
<div v-if="open" class="modal">
<p>Hello 1024nav.com !</p>
<button @click="open = false">关闭</button>
</div>
</template>
<style scoped>
.modal {
position: fixed;
z-index: 999;
top: 20%;
left: 50%;
width: 300px;
margin-left: -150px;
}
</style>
然后在组件使用它。
<div class="container">
<h1>1024nav</h1>
<Modal />
</div>
我们可以看到,Modal 组件会插入到 class 为 container
的元素上,这样 fixed 布局就会有问题,至于什么问题,自己去试试。。。我们来看如何解决
我们只需要稍微改动下代码,在弹窗的标签用 Teleport
包裹一下即可,Teleport
有一个 to
属性,可以是一个 class 选择器,或者 dom 元素对象。我们来插入到 body 元素下。
<Teleport to="body">
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</Teleport>
这样就可以实现 fixed 布局功能了。
使用
to
要确保挂载的元素已经在Teleport
组件前已经挂载完成。
禁用 Teleport
Teleport
提供了另一个属性 disabled
,可以根据条件控制插入。
<Teleport :disabled="isMobile"> ... </Teleport>
共享 DOM 元素
如果 to 的目标是同一个,会根据 Teleport
的使用顺序一起插入到指定的元素上。
<Teleport to="#modals">
<div>A</div>
</Teleport>
<Teleport to="#modals">
<div>B</div>
</Teleport>
结果为
<div id="modals">
<div>A</div>
<div>B</div>
</div>