跳到主内容

vue3如何利用Teleport内置组件来封装modal弹窗组件

· 3分钟阅读

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>