ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] >[success] # Teleport 传送门功能 这章我们讲解一下 **vue3** 提供给我们的 **Teleport 传送门** ,我们看一看 **传送门** 是什么,我们该 **如何使用它** 呢? 需求:假如我们需要写一个 **点击按钮弹出一个黑色半透明弹窗,遮盖整个屏幕** ,我们的 **布局代码以及样式** 是这样写的: **点击前** ![](https://img.kancloud.cn/f4/91/f491ed4a7d41fdfd267756cea31923a2_701x386.png) **点击后** ![](https://img.kancloud.cn/3a/bb/3abb64aa2f0b92ff07fc865647ad463d_617x346.png) **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Teleport 传送门功能</title> <style> .area{ position: absolute; left: 50%; top: 50%; /* transform: translateX(-50%); transform: translateY(-50%); */ /* 上面这样写下面的会把上面的样式覆盖掉,所以要用简写的形式*/ transform: translateY(-50%, -50%); width: 200px; height: 300px; background: green; } .mask{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: #000; opacity: .5; } </style> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // Teleport 传送门 const app = Vue.createApp({ data(){ return { show: false } }, methods: { handleBtnClick(){ this.show = !this.show } }, template: ` <div class="area"> <button @click="handleBtnClick">按钮</button> <div class="mask" v-show="show"></div> </div> ` }) const vm = app.mount('#root') </script> </html> ~~~ 你会发现 **蒙层大小并不是我们想要的全屏的大小** ,这是因为 **黑色蒙层是绝对定位的是自己的父级 area 这个元素,而 area 这个元素的大小只有200 * 300 的大小** ,如果 **我们想实现黑色遮罩层全屏,通常需要把这个遮罩层放入到 body 内,从而变成 body 直接的子级,这样绝对定位的就是body** ,这样写就会 **非常非常的麻烦** ,而 **vue3** 给我们提供了一个 **teleport标签(传送门)** ,我们只需要 **用teleport标签 将黑色弹层包裹,并且写上 to 属性, to 属性 内写入我们要传入到的标签名称,就可以将弹窗传入到想要传入的标签内** , >[success] ## 传送门功能实现传送弹窗功能 **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Teleport 传送门功能</title> <style> .area{ position: absolute; left: 50%; top: 50%; /* transform: translateX(-50%); transform: translateY(-50%); */ /* 上面这样写下面的会把上面的样式覆盖掉,所以要用简写的形式*/ transform: translateY(-50%, -50%); width: 200px; height: 300px; background: green; } .mask{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: #000; opacity: .5; } </style> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // Teleport 传送门 const app = Vue.createApp({ data(){ return { show: false } }, methods: { handleBtnClick(){ this.show = !this.show } }, template: ` <div class="area"> <button @click="handleBtnClick">按钮</button> <teleport to="body"> <div class="mask" v-show="show"></div> </teleport> </div> ` }) const vm = app.mount('#root') </script> </html> ~~~ ![](https://img.kancloud.cn/53/53/535339a72dc4682f63385b6025b96206_726x387.png) 这样就实现了我们想要的效果, **全屏的遮盖效果** , 然而我们也可以 **根据 id 传送到指定的标签内** ,下面的案例中就是 **将弹窗盒子传入了 id 为 hello 的元素中**,代码如下: ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Teleport 传送门功能</title> <style> .area{ position: absolute; left: 50%; top: 50%; /* transform: translateX(-50%); transform: translateY(-50%); */ /* 上面这样写下面的会把上面的样式覆盖掉,所以要用简写的形式*/ transform: translateY(-50%, -50%); width: 200px; height: 300px; background: green; } .mask{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: #000; opacity: .5; } </style> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> <div id="hello"></div> </body> <script> // Teleport 传送门 const app = Vue.createApp({ data(){ return { show: false } }, methods: { handleBtnClick(){ this.show = !this.show } }, template: ` <div class="area"> <button @click="handleBtnClick">按钮</button> <teleport to="#hello"> <div class="mask" v-show="show"></div> </teleport> </div> ` }) const vm = app.mount('#root') </script> </html> ~~~ 编译后的代码如下, **可以看到遮罩层被放入到 id 为 hello 的盒子中** ![](https://img.kancloud.cn/14/6c/146c1aa42c2430c8fb1ec13a412858d3_532x315.png) >[success] # 总结 我们可以 **封装组件** 时,有弹窗的需求,可以用 **teleport 用传送门功能** 。