Vue3 - Teleport 传送门(详细教程)

2,567 阅读3分钟
前言

对比 Vue2 ,引出并展开 Vue3 。

本文讲述了 Teleport 传送门是什么,以及使用方法和代码示例。

介绍

学过 React 的同学可能知道, Portal 也提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀方案,当然咱们大名鼎鼎的 Vue3 也做到了,关于这方面的功能需求,第三方库也是有很多的,这里就不详谈了,感兴趣的可以自己去了解。

Teleport 传送门是 Vue3 内置的组件,它是一种能够将我们的模板移动到 DOM 中 Vue app 之外其他位置的技术。

Vue2 示例

先拿 Vue2 举例,上来讲概念直接上 Vue3 代码有些朋友肯定不太懂。

我们市场上很多项目,大部分都包含弹框,提示用户一些信息,比如 ElementUI 的弹框组件。

image.png

这样的弹框,我们在开发的时候都会选择创建一个组件,将来有页面需要用的时候,直接引入,再传入相应的配置即可。


咱们先来看一下 Vue2 中如何实现弹框。

在 components 目录下,新建 modal.vue ,这个文件咱们用作弹框组件。

<template>
    <div>
        <button @click="flag = true">打开弹框</button>
        <div v-if="flag" class="modal">
            <div>
            <h1>Hello</h1>
            <button @click="flag = false">
                关闭
            </button>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            flag: false
        }
    }
}
</script>

<style>
.modal {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background-color: rgba(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-color: white;
  width: 600px;
  height: 300px;
  padding: 5px;
  border-radius: 15px;
}
</style>

然后引入该组件:

<template>
  <div>
     <Modal />
  </div>
</template>

<script>
import Modal from './components/modal.vue'
export default {
  components: { Modal },
}
</script>

然后咱们打开控制台,看一下 DOM 结构,可以发现咱们的页面内容全部被套在 #app 这个元素下,而我们的弹框组件则是被套在父组件的中,也就是说哪个页面引用了弹框组件,弹框组件就被嵌套在此。

image.png

由此我们知道,弹框是被深度嵌套的 div 中渲染的,那么问题来了,此时处理嵌套组件的定位与 z-index 样式都会变得很困难,也就是由于你弹框组件受父组件影响,所以你在写样式的时候都需要考虑到父组件,比如 z-index 不能太高,定位不能使用绝对定位等,非常恶心。

Vue3 示例

那么有没有一种办法,既能享受到 Vue 带来的功能,又不受父组件影响呢?答案是有,有请我们的主角登场,废话不多说,马上用 Vue3 重构一把。

首先打开项目根目录下 index.html 文件,在 <div id="app"></div> 下加入一段代码:

image.png

为什么要加入这一行呢,一会你就知道了。

加完之后呢,我们打开刚才用 Vue2 编写的弹框组件,咱们做一些修改:

<template>
    <button @click="flag = true">打开弹框</button>
    <!-- 注意这里,把刚才在 index.html 加入的节点,放到这里 ↓↓↓ -->
    <!-- 然后被teleport包裹的内容,就会传送到#modal节点上(也就是成功跑到了#app节点之外) -->
    <!-- 虽然跑到了#app节点之外,但依然可以享有vue带来的功能 -->
    <teleport to="#modal">
        <div v-if="flag" class="modal">
            <div>
            <h1>Hello</h1>
            <button @click="flag = false">
                关闭
            </button>
            </div>
        </div>
    </teleport>
</template>

<script>
export default {
    data() {
        return {
            flag: false
        }
    }
}
</script>

<style>
.modal {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background-color: rgba(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-color: white;
  width: 600px;
  height: 300px;
  padding: 5px;
  border-radius: 15px;
}
</style>

再比如,我们直接把弹框传送到 body 节点上,直接改 to="body" 属性即可。

非常的简单,省时省力。

写在后面

这些示例代码都是可以运行的,如果你还是不懂,可以自己亲自复制代码跑起来。

SEO

Vue3 teleport 传送门官方文档,vue3 Teleport 传送门,vue3之teleport(传送门)的使用,极速上手 VUE 3 teleport传送门组件及使用语法,VUE 3 teleport传送门,Vue 3 任意传送门,vue3中teleport传送门与emits事件的使用,VUE3 teleport传送门用于做什么,详解Vue3中Teleport的使用,Vue3 - Teleport 传送门(详细教程)。