首页 > 其他分享 >记录-VueJs中如何使用Teleport组件

记录-VueJs中如何使用Teleport组件

时间:2023-04-07 17:48:58浏览次数:32  
标签:模态 Teleport DOM VueJs 50% 组件 结构

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

DOM结构相对比较复杂,层级嵌套比较深的组件内,需要根据相对应的模块业务处理一些逻辑,该逻辑属于当前组件

但是从整个页面应用的视图上看,它在DOM中应该被渲染在整个vue应用外部的其他地方,不能影响组件的结构

比较常见的应用场景:就是全屏的模态框,控制元素的位置,也是可以处理的,但是比较麻烦

在理想情况下,我们希望在具体的组件中,给元素绑定的事件,与具体要控制的DOM元素结构在同一个组件中,具体的位置处,保持一定的相关联性

而不用特意的把一些DOM结构给分离出去,然而,在同一组件中,触发模态框的按钮和模态框本身在同一组件中

因为他们都与组件的开关状态有相关联,模态框与按钮一起渲染在应用DOM结构很深的地方,会导致模态框的css布局位置非常难控制

鉴于这样的场景和困难,Vue官方提供了一个Teleport组件,很好的可以解决这个问题,让开发者不需要顾虑DOM结构的问题

01-组件套组件层次结构很深时

比如:现在有两个组件,父组件,子组件,在后代组件内,添加一个按钮,弹出一个模态框,让它在页面垂直水平居中显示

如下所示,父组件如下所示App.vue

<template>
    <div class="App">
        我是父组件
        <Child />
    </div>
</template>
<script setup>
    import Child from "./Child.vue"
</script>
<style>
.App {
    width: 400px;
    height: 400px;
    background:red;
}
</style>

如下是Child组件,示例代码如下所示Child.vue,我们需要在孙(后代)组件,添加一个按钮,点击按钮,弹出一个弹框,水平垂直居中显示在页面中央

<template>
    <div class="child">
      <p>我是子组件</p>
        <button @click="isModel=true">打开模态框</button>
        <div class="mask-dialog" v-if="isModel">
             <div class="box">
                  <h2>我是标题</h2>
                  <div>我是弹框内容</div>
                  <div>
                      <button @click="isModel=false">关闭</button>
                  </div>
             </div>
        </div>
    </div>
</template>
<script setup>
import { ref } from "vue";
let isModel = ref(false);
</script>
<style>
.child {
    width: 300px;
    height:300px;
    background:green;
}
/**灰色遮罩层 */
  .mask-dialog {
    width: 100%;
    height:100%;
    position:absolute;
    left:0;
    top:0;
    background:rgba(0,0,0,0.5)
  }
  
  .box {
    width: 200px;
    height:200px;
    position:absolute;
    left:50%;
    top:50%;
    transform:translate(-50%,-50%);
    background:pink;
    text-align:center;
  }
</style>

上面的子组件中有一个button按钮来触发打开当前组件的模态框,里面存在着控制弹框的显示和隐藏的逻辑,当嵌套的组件比较深,复杂时

如果父级元素存在定位,那在控制子元素的位置时,用csstransform或者position:absolute,参照对象的变更,会破坏布局结构,会出现一些css样式

控制的问题,解决起来会非常的痛苦

那这个Teleport组件就是为了解决这类问题,可以将指定的DOM结构片段,独立于到组件外面去,不受当前组件布局结构的影响

经过Teleport的修改后

<template>
    <div class="child">
      <p>我是子组件</p>
        <button @click="isModel=true">打开模态框</button>
        <Teleport to="body">
            <div class="mask-dialog" v-if="isModel">
                 <div class="box">
                      <h2>我是标题1</h2>
                      <div>我是弹框内容</div>
                      <div>
                          <button @click="isModel=false">关闭</button>
                      </div>
                 </div>
            </div>
        </Teleport>  
    </div>
</template>
<script setup>
import { ref } from "vue";
let isModel = ref(false);
</script>
<style>
.child {
    width: 300px;
    height:300px;
    background:green;
}
/**灰色遮罩层 */
  .mask-dialog {
    width: 100%;
    height:100%;
    position:absolute;
    left:0;
    top:0;
    background:rgba(0,0,0,0.5)
  }
  
  .box {
    width: 200px;
    height:200px;
    position:absolute;
    left:50%;
    top:50%;
    transform:translate(-50%,-50%);
    background:pink;
    text-align:center;
  }
</style>

<Teleport>接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,或id,也可以是一个 DOM 元素对象。这段代码的作用就是告诉 Vue把以下模板片段传送到 body 标签下

<Teleport to="#some-id">html结构代码</Teleport>
<Teleport to=".some-class">html结构代码</Teleport>
<Teleport to="body">html结构代码</Teleport>
<Teleport to="html">html结构代码</Teleport>

02-Teleport组件

它是Vue官方提供的一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去 也就是一种能够将我们的组件html结构移动到指定位置的技术

<teleport to="移动到指定的位置,可以是html,body,或id,class">
   里面是Html结构模板内容
</teleport>

注意

<Teleport> 挂载时,传送的 to 目标必须已经存在于DOM中。理想情况下,这应该是整个 Vue 应用 DOM 树外部的一个元素。如果目标元素也是由 Vue 渲染的,你需要确保在挂载 <Teleport> 之前先挂载该元素

这个teleport将指定的模板html,放置到页面当中指定的位置处,它是有条件的,不是可以任意传送的

在安装组件之前,目标元素必须存在,即,目标不能由组件本身呈现,理想情况下应该位于整个Vue组件树之外。

如下代码是不行的

<template>
    <div class="header">
        <Teleport to=".content">
            <div>我是头部的内容</div>
        </Teleport>
         
    </div>
    <div class="footer">
        底部内容
        <div class="content"></div>
    </div>
</template>
<script setup>
</script>
<style lang="less">
h1 {
    color: red;
}
</style> 

03-需要知道的

teleport只是改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。也就是说,如果 <Teleport> 包含了一个组件,那么该组件始终和这个使用了 <teleport> 的组件保持逻辑上的父子关系。传入的 props 和触发的事件也会照常工作。

这也意味着来自父组件的注入也会按预期工作,子组件将在 Vue Devtools 中嵌套在父级组件下面,而不是放在实际内容移动到的地方

位置移动了,提现在结构模板上,但是数据逻辑依旧存在关联的

04-如何禁用 Teleport

在某些场景下可能需要视情况禁用 <Teleport>。举例来说,我们想要在桌面端将一个组件当做浮层来渲染,但在移动端则当作行内组件。我们可以通过对 <Teleport> 动态地传入一个 disabled prop 来处理这两种不同情况

<Teleport :disabled="isMobile">
  ...
</Teleport>

05-多个 Teleport 共享目标时

一个可重用的模态框组件可能同时存在多个实例。对于此类场景,多个 <Teleport> 组件可以将其内容挂载在同一个目标元素上,而顺序就是简单的顺次追加,后挂载的将排在目标元素下更后面的位置上

比如下面这样的用例

<Teleport to=".content">
  <div>A</div>
</Teleport>
<Teleport to=".content">
  <div>B</div>
</Teleport>

渲染的结果为

<div class="content">
  <div>A</div>
  <div>B</div>
</div>

总结

这个teleport组件在实际开发中还是很实用的,能够解决当组件嵌套层级很深,而后代组件中的模板,想要脱离当前组件结构,解决css布局层面的干扰,那就可以用这个teleport组件

本文转载于:

https://juejin.cn/post/7217731723509547069

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

标签:模态,Teleport,DOM,VueJs,50%,组件,结构
From: https://www.cnblogs.com/smileZAZ/p/17296909.html

相关文章

  • uni-app 弹出层组件的实现
    uni-app弹出层组件的实现以下是一个简单的uni-app弹出层组件的实现代码示例,它可以根据传递的属性来控制弹出层的显示和隐藏:<template><viewclass="overlay"v-show="visible"@click="close":class="{ 'center':position==='cente......
  • uni-app 日历组件的实现
    uni-app日历组件的实现以下是一个基于uni-app的简单日历组件实现代码,包括了日历的基本布局和日期选择功能:<template><viewclass="calendar"><viewclass="calendar-header"><viewclass="calendar-prev"@click="prevMonth">上个月......
  • Ioc底层核心原理-组件扫描过滤器
              ......
  • 支持多种文件(docx、excel、pdf)预览的vue组件库,支持vue2/3。
    原文链接https://github.com/501351981/vue-office 功能特色一站式:提供docx、pdf、excel多种文档的在线预览方案,有它就够了简单:只需提供文档的src(网络地址)即可完成文档预览体验好:选择每个文档的最佳预览方案,保证用户体验和性能都达到最佳状态安装#docx文档预览组件......
  • 使用vue2从零开始搭建自己的组件库(完整版)
    前言在前端开发中,除了常用的UI组件库以外,我们还会涉及到基于公司业务,需要定制化开发一些业务组件,还有随着项目的增多,开发人员的增多,为了提高工作效率,我们就需要统一管理好已开发好的业务组件。这时候我们就需要搭建自己的组件库,因为涉及到一些公司的业务,我们只能发布到私服的npm......
  • uni-app 滚动通知组件的实现
    uni-app滚动通知组件的实现一、实现思路二、使用scroll-view组件实现<template><viewclass="notice"><scroll-viewclass="notice-scroll":scroll-y="true":scroll-with-animation="true":scroll-t......
  • 2023.04.06 - vue组件中动态指定监听的值
    业务场景:高拍仪给出的视频信息API回调里会不断返回图像数据。因为有主副摄像图像信息,并且两个图像信息会二选一展示在DOM容器里。所以就是二对一的关系。//主摄像数据letpriPic:string='';//副摄像数据letsubPic:string='';//展示在容器的数据=主摄像数据||副摄像......
  • 可视化组件g2之分组箱型图、柱形图、散点图简单使用
    <!--引入G2文件--><scriptsrc="./plugins/g2.v5.min.js"></script><style> .container{  display:flex; } .div{  height:500px; }</style><!--创建图表容器--><divclass="container"> ......
  • 二次封装ui组件,如何做到属性,作用域插槽以及 实例方法的穿透使用
    A页面:在使用二次封装的组件<MyInputref='inputRef'v-model='data'placeholder='xxxx'><template#prepend>......</template><template#append>......</template></MyInput>......
  • 2023.04.06 - 使用mixin动态混入,对vue组件中的数据做兼容经验总结(xp)
    业务场景:在一个高拍仪的硬件设备中,厂家给了两套不同的API,分别支持winXP和winXP以上版本的系统,而这两套API的实现方式截然不同,一套使用的是http通信,一套是使用scoket通信,方法的调用自然也是不同。我需要在同一组件兼容这两套代码。这种需求下很明显,我除了修改组件里的函数方法,......