网站首页 > 技术文章 正文
<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
1,使用场景:
一个组件模板的一部分在逻辑上从属于该组件,但从整个应用视图的角度来看,它在 DOM 中应该被渲染在整个 Vue 应用外部的其他地方;
也就是说我有一个全屏的弹出框(模态框)或 Toast 轻提示 组件,可能会在多个组件中使用到,但是由于节点嵌套的太深,我想把它的dom元素放在最外层的容器上面;通过组件传参控制它的显示于隐藏;
这样做的好处是:处理嵌套组件的定位、z-index 和样式就会变得简单;不会造成样式污染;
而且管理起来反而会方便容易很多;
2,搭配组件使用
<Teleport> 只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。也就是说,如果 <Teleport> 包含了一个组件,那么该组件始终和这个使用了 <teleport> 的组件保持逻辑上的父子关系。传入的 props 和触发的事件也会照常工作。
这也意味着来自父组件的注入也会按预期工作,子组件将在 Vue Devtools 中嵌套在父级组件下面,而不是放在实际内容移动到的地方。
效果图如下:
点击按钮弹出模态框,点击OK关闭模态框,且渲染的节点位置是在 body(或任意节点)下面的;
实现如下
父组件:
<script setup>
import { reactive, ref, watch, onMounted } from "vue";
// 引入模态框组件
import Modal from "../../components/component/Modal.vue";
let isShow = ref(false);
// 显示模态框
const showModel = () => {
isShow.value = true;
};
</script>
<template>
<div class="container">
<!-- 预留Teleport组件的位置 可以放到这里 to=".container" -->
</div>
<div id="container">
<!-- 预留Teleport组件的位置 可以放到这里 to="#container -->
</div>
<div class="teleport">
<h4>teleport组件演示</h4>
<button @click="showModel">点击弹出模态框</button>
<!-------------------------------------Teleport使用 ------------------------------------>
<Teleport to="body">
<!-- 使用这个 modal 组件,传入 prop -->
<modal :show="isShow" @close="isShow = false">
<template #header>
<h3>custom header</h3>
</template>
</modal>
</Teleport>
</div>
</template>
<style scoped></style>
子组件Modal.vue:
<script setup>
const props = defineProps({
show: Boolean,
});
</script>
<template>
<Transition name="modal">
<div v-if="show" class="modal-mask">
<div class="modal-container">
<div class="modal-header">
<slot name="header">default header</slot>
</div>
<div class="modal-body">
<slot name="body">default body</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" @click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</Transition>
</template>
<style>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
transition: opacity 0.3s ease;
}
.modal-container {
width: 300px;
margin: auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* 对于 transition="modal" 的元素来说
* 当通过 Vue.js 切换它们的可见性时
* 以下样式会被自动应用。
*
* 你可以简单地通过编辑这些样式
* 来体验该模态框的过渡效果。
*/
.modal-enter-from {
opacity: 0;
}
.modal-leave-to {
opacity: 0;
}
.modal-enter-from .modal-container,
.modal-leave-to .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
</style>
3,to属性的使用
<Teleport> 接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串(如:to=".container"、to="#container),也可以是一个 DOM 元素对象(如:to="body")。
这段代码的作用就是告诉 Vue把以下模板片段传送到 你所期望的标签下面。
4,禁用 Teleport
在某些场景下可能需要视情况禁用 <Teleport>,需要添加disabled为false即可;
<Teleport to="body" :disabled="false">
<!-- 使用这个 modal 组件,传入 prop -->
<modal :show="isShow" @close="isShow = false">
<template #header>
<h3>custom header</h3>
</template>
</modal>
</Teleport>
那么此时这个组件就相当于普通的弹窗组件,不再进行移动了;
5,多个 Teleport 共享目标
一个可重用的模态框组件可能同时存在多个实例。对于此类场景,多个 <Teleport> 组件可以将其内容挂载在同一个目标元素上,而顺序就是简单的顺次追加,后挂载的将排在目标元素下更后面的位置上。
比如下面这样的用例:
<Teleport to="#modals">
<div>A</div>
</Teleport>
<Teleport to="#modals">
<div>B</div>
</Teleport>
渲染的结果为:
html
<div id="modals">
<div>A</div>
<div>B</div>
</div>
猜你喜欢
- 2025-01-02 JavaScript字符串toString()方法教程
- 2025-01-02 网页三维CAD中加载和保存STEP模型
- 2025-01-02 在.NET Web API中设置响应输出Json数据格式的两种常用方式
- 2025-01-02 剖析Selenium代码执行时元素查找失败的缘由
- 2025-01-02 H5的Canvas绘图——使用fabricjs绘制一个可多选的随机9宫格
- 2025-01-02 jscanify:支持 Node.js/浏览器/React 移动文档扫描仪
- 2025-01-02 js事件机制详解
- 2025-01-02 Java ArrayList用法详解附代码示例
- 2025-01-02 如何用枚举快速提高编程效率,数据元素快速对应,小枚举大作用
- 2025-01-02 这段代码,还有优化的地方吗?
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)