---
title: "vue3 使用teleport(传送门)组件实现一个模态框"
id: "3199"
type: "post"
slug: "vue3-%e4%bd%bf%e7%94%a8teleport%e4%bc%a0%e9%80%81%e9%97%a8%e7%bb%84%e4%bb%b6%e5%ae%9e%e7%8e%b0%e4%b8%80%e4%b8%aa%e6%a8%a1%e6%80%81%e6%a1%86"
published_at: "2020-12-22T02:35:21+00:00"
modified_at: "2020-12-22T02:43:36+00:00"
url: "https://seq.ink/all/3199.html"
markdown_url: "https://seq.ink/all/3199.html.md"
excerpt: "vue3 使用teleport(传送门)组件实现一个模态框 vue3的teleport功能类似于react的Portals，portals提供了一种将子节点渲染到存在于父组件以外都dom节点解决方案，vue3的teleport与react的 ..."
taxonomy_category:
  - "ALL"
  - "Coding代码堆"
---

# vue3 使用teleport(传送门)组件实现一个模态框

`vue3`的`teleport`功能类似于`react`的`Portals`，`portals`提供了一种将子节点渲染到存在于父组件以外都dom节点解决方案，`vue3`的`teleport`与`react`的`Portals`功能类似，且更加好用。

在vue2下 要实现类似功能需要通过[portal-vue](https://github.com/LinusBorg/portal-vue)
库去实现。

## 我们为什么需要Teleport

`teleport`是一种能将我们的模板移动到DOM中Vue App之外的技术，有点类似多啦A梦的“传送门”

使用场景：像`modals`，`toast`等这样的元素，很多情况下我们将它完全和我们的Vue应用DOM完全剥离，管理起来相反会方便许多

原因在于如果我们嵌套在Vue某个组件内部，那么处理组件的定位、z-index和样式就会变得很困难

另外，像modals，toats等这样的元素需要使用到Vue组件状态的值我们可能需要将状态放入到Vuex中同一管理，而teleport可以直接使用组件的data或prpos。然后在Vue应用范围之外渲染它。

> 以上引用自[Gopal1](https://www.jianshu.com/p/1ecf5006b1ae?utm_campaign=haruki&utm_content=note&utm_medium=seo_notes&utm_source=recommendation)
>  Vue 3 任意传送门——Teleport
> 
>  修改了“另外，想modals…..然后在Vue应用范围之外渲染它”

## 使用Teleport实现一个模态框Deom

新建一个模态框组件 `./src/components/modal.vue`  
 注意 在Vue3中拥有`Fragments`特特性可以允许组件存在多个根，所以一下模板写法是合法的。

```
<template>
  <button @click="modalOpen = true">开启模态框</button>
  <teleport to="body">
    <div v-if="modalOpen" class="modal">
      <div>
        我是一个模态框
        <button @click="modalOpen = false">关闭模态框</button>
      </div>
    </div>
  </teleport>
</template>

<script>
export default {
  data() {
    return {
      modalOpen: false,
    };
  },
};
</script>
```

注意 `teleport`是`Vue3`中的一个全局组件你可以在任意地方使用

其中的to属性是要把组件下内容挂载到哪里去，参数是一个选择器 我这里就直接挂载到body标签下`<teleport to="body">` `teleport`标签内是你要“传送的内容” 我们可以直接使用模板下的data状态对模态框的显示进行操作。

随后追加上css

```
<style scopde>
.modal {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.modal div {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: white;
  width: 300px;
  height: 300px;
  padding: 5px;
}
</style>
```

然后你就可以在任意组件使用我们的模态框了但是注意

**！如果你是使用Vite构建的项目在引入组件时必须携带组件后缀，让Vite知道该如何处理这个文件**

`import Modal from "./modal.vue";`

然后就可以使用了。
