首页 > 其他分享 >第二十六篇 vue - 深入组件 - 内置组件 - Teleport

第二十六篇 vue - 深入组件 - 内置组件 - Teleport

时间:2023-04-01 11:57:58浏览次数:39  
标签:模态 Teleport vue DOM 元素 Vue 组件

Teleport

<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去

基本用法

有时我们可能会遇到这样的场景:一个组件模板的一部分在逻辑上从属于该组件,但从整个应用视图的角度来看,它在 DOM 中应该被渲染在整个 Vue 应用外部的其他地方

这类场景最常见的例子就是全屏的模态框。理想情况下,我们希望触发模态框的按钮和模态框本身是在同一个组件中,因为它们都与组件的开关状态有关。但这意味着该模态框将与按钮一起渲染在应用 DOM 结构里很深的地方。这会导致该模态框的 CSS 布局代码很难写

试想下面这样的 HTML 结构

<div class="outer">
  <h3>Tooltips with Vue 3 Teleport</h3>
  <div>
    <MyModal />
  </div>
</div>

接下来我们来看看 <MyModal> 的实现

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

<template>
  <button @click="open = true">Open Modal</button>

  <div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
  </div>
</template>

<style scoped>
.modal {
  position: fixed;
  z-index: 999;
  top: 20%;
  left: 50%;
  width: 300px;
  margin-left: -150px;
}
</style>

这个组件中有一个 <button> 按钮来触发打开模态框,和一个 class 名为 .modal 的 <div>,它包含了模态框的内容和一个用来关闭的按钮。

当在初始 HTML 结构中使用这个组件时,会有一些潜在的问题:

position: fixed 能够相对于浏览器窗口放置有一个条件,那就是不能有任何祖先元素设置了 transform、perspective 或者 filter 样式属性。也就是说如果我们想要用 CSS transform 为祖先节点 <div class="outer"> 设置动画,就会不小心破坏模态框的布局!

这个模态框的 z-index 受限于它的容器元素。如果有其他元素与 <div class="outer"> 重叠并有更高的 z-index,则它会覆盖住我们的模态框。
<Teleport> 提供了一个更简单的方式来解决此类问题,让我们不需要再顾虑 DOM 结构的问题。让我们用 <Teleport> 改写一下 <MyModal>

<button @click="open = true">Open Modal</button>

<Teleport to="body">
  <div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
  </div>
</Teleport>

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

注意

<Teleport> 挂载时,传送的 to 目标必须已经存在于 DOM 中。理想情况下,这应该是整个 Vue 应用 DOM 树外部的一个元素。如果目标元素也是由 Vue 渲染的,你需要确保在挂载 <Teleport> 之前先挂载该元
搭配组件使用
<Teleport> 只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。也就是说,如果 <Teleport> 包含了一个组件,那么该组件始终和这个使用了 <teleport> 的组件保持逻辑上的父子关系。传入的 props 和触发的事件也会照常工作。

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

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

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

这里的 isMobile 状态可以根据 CSS media query 的不同结果动态地更新
多个 Teleport 共享目标

一个可重用的模态框组件可能同时存在多个实例。对于此类场景,多个 <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>

标签:模态,Teleport,vue,DOM,元素,Vue,组件
From: https://www.cnblogs.com/caix-1987/p/17278340.html

相关文章

  • 第二十八篇 vue - 深入组件 - 动态组件 - component
    component动态组件就是动态变化的组件,和动态样式一样,通过用户的操作来确定是什么类型的组件。动态样式是绑定:style,动态组件则是绑定:is在vue中,实现Tab切换主要有三种方式:使用动态组件,使用vue-router路由,使用第三方插件。本文将详细介绍Vue动态组件所谓动态组件就是让多......
  • [vue3]npm创建环境
    1.npm安装vuecli[root@Python20230401VUE3]#npminstall-g@vue/cli2.查看vue版本[root@Python20230401VUE3]#vue--version@vue/cli5.0.83.创建项目[root@Python20230401VUE3]#vuecreatehello-world4.执行项目$cdhello-world$npmrunserve......
  • 第二十一篇 vue - 深入组件 - 依赖注入 - provide 和 inject
    Prop逐级透传问题provide和inject可以帮助我们解决这一问题。[1]一个父组件相对于其所有的后代组件,会作为依赖提供者任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖Prop逐级透传问题通常情况下,当我们需要从父组件向子组件传递数据时,会使用pr......
  • vue2 + sass + sass-loader
    本地vue脚手架版本:5.0.8本地node版本:v18.13.0项目创建:vueinitwebpackdemo由于项目本身不支持sass,需要首先安装:npminstallsasssass-loader-D,记住:此处无需安装node-sass,安装后报错。由于sass和sass-loader版本不兼容会出现报错(TypeError:this.getOptionsisnotafunc......
  • vue (一)
     vue是一套构建用户界面的前端框架。 构建用户界面指的是用vue往html中填充数据。 框架指的是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能。 vue指令、组件(ui的复用)、路由、vuex、vue组件库 只有把上面罗列的内容掌握之后才有开发vue项目的能力。......
  • VUE分别使用普通方法、计算属性、监听器完成简易计算器
    VUE分别使用普通方法、计算属性、监听器完成简易计算器声明:本方法使用VUE完整框架独立模块组件来实现TOP:实现效果Ⅰ:完整框架Ⅱ:框架实现案例组件功能细分1.APP组件总组件,管理所有组件(每个单独的组件最后都汇总到APP组件里,便于管理)管理汇总:Methodss组件、Watchss......
  • process.env.NODE_ENV 开发环境配置详解(Vue项目)
    开发环境与生产环境下切换baseURL增加.env.development文件NODE_ENV='development'VUE_APP_BASE_URL='/api'增加.env.development文件NODE_ENV='production'VUE_APP_BASE_URL=''使用constaxiosRequest=axios.create({base......
  • 我的第一个项目(七):(解决问题)Vue中canvas无法绘制图片
    好家伙, 现在,我想要把我的飞机大战塞到我的主页里去,想办法把文件导入 然后,直接死在第一步,图片渲染都成问题 先用vue写一个测试文件来测试canvas的绘制<template><div><divref="stage"></div><button@click="drawsth()">添加</button><imgsrc......
  • Vue 2中实现数字滚动效果
     代码:<template><divclass="statistics-num"><!--显示当前数字,不使用逗号分隔符--><spanclass="num">{{currentVal.toString()}}</span><!--显示当前数字,用逗号分隔符--><!--<spanclass="num......
  • Vue引用富文本编辑器
    1.在package.json加上并安装依赖"devDependencies":{"@jsdawn/vue3-tinymce":"^1.1.7",}2.在页面中引入importVue3Tinymcefrom"@jsdawn/vue3-tinymce";3.使用<vue3-tinymcev-model="item.blockDataObj.text":s......