vue3中Teleport的用法以及使用场景

1. 基本概念

Teleport 是 Vue3 提供的一个内置组件,它可以将组件的内容传送到 DOM 树的任何位置,而不受组件层级的限制。这在处理模态框、通知、弹出菜单等需要突破组件层级限制的场景中特别有用。

1.1 基本语法

<template><teleport to="body"><!-- 这里的内容会被传送到 body 标签下 --><div class="modal"><!-- 模态框内容 --></div></teleport>
</template>

2. 常见使用场景

2.1 模态框

<!-- Modal.vue -->
<template><teleport to="body"><div v-if="isOpen" class="modal-overlay"><div class="modal"><div class="modal-header"><h3>{{ title }}</h3><button @click="close">×</button></div><div class="modal-body"><slot></slot></div><div class="modal-footer"><slot name="footer"><button @click="close">关闭</button></slot></div></div></div></teleport>
</template><script setup>
const props = defineProps({isOpen: Boolean,title: String
})const emit = defineEmits(['update:isOpen'])const close = () => {emit('update:isOpen', false)
}
</script><style scoped>
.modal-overlay {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.5);display: flex;justify-content: center;align-items: center;z-index: 1000;
}.modal {background: white;padding: 20px;border-radius: 8px;min-width: 300px;
}
</style>

2.2 通知提示

<!-- Notification.vue -->
<template><teleport to="#notifications-container"><divv-if="show":class="['notification', type]"@click="close"><div class="notification-content">{{ message }}</div></div></teleport>
</template><script setup>
import { ref, onMounted } from 'vue'const props = defineProps({message: String,type: {type: String,default: 'info'},duration: {type: Number,default: 3000}
})const show = ref(true)const close = () => {show.value = false
}onMounted(() => {if (props.duration > 0) {setTimeout(close, props.duration)}
})
</script><style scoped>
.notification {position: fixed;top: 16px;right: 16px;padding: 12px 24px;border-radius: 4px;cursor: pointer;transition: all 0.3s;
}.info {background: #e6f7ff;border: 1px solid #91d5ff;
}.success {background: #f6ffed;border: 1px solid #b7eb8f;
}.error {background: #fff2f0;border: 1px solid #ffccc7;
}
</style>

2.3 上下文菜单

<!-- ContextMenu.vue -->
<template><teleport to="body"><divv-if="show"class="context-menu":style="position"><slot></slot></div></teleport>
</template><script setup>
import { ref, computed } from 'vue'const props = defineProps({show: Boolean,x: Number,y: Number
})const position = computed(() => ({left: props.x + 'px',top: props.y + 'px'
}))
</script><style scoped>
.context-menu {position: fixed;background: white;border: 1px solid #eee;border-radius: 4px;padding: 8px 0;min-width: 160px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
</style>

3. 高级用法

3.1 动态目标

<template><teleport :to="target"><div class="content">动态传送的内容</div></teleport>
</template><script setup>
import { ref, onMounted } from 'vue'const target = ref('body')onMounted(() => {// 可以根据条件动态改变目标if (window.innerWidth < 768) {target.value = '#mobile-container'}
})
</script>

3.2 多个 Teleport 到同一目标

<template><teleport to="#notifications"><div class="notification">通知 1</div></teleport><teleport to="#notifications"><div class="notification">通知 2</div></teleport>
</template>

3.3 条件性传送

<template><teleport to="body" :disabled="isMobile"><div class="modal"><!-- 在移动端不会被传送,保持原位置 --></div></teleport>
</template><script setup>
import { ref, onMounted } from 'vue'const isMobile = ref(false)onMounted(() => {isMobile.value = window.innerWidth < 768window.addEventListener('resize', () => {isMobile.value = window.innerWidth < 768})
})
</script>

4. 实际应用示例

4.1 全局加载指示器

<!-- LoadingIndicator.vue -->
<template><teleport to="body"><div v-if="loading" class="loading-overlay"><div class="loading-spinner"></div><div class="loading-text">{{ message }}</div></div></teleport>
</template><script setup>
defineProps({loading: Boolean,message: {type: String,default: '加载中...'}
})
</script><style scoped>
.loading-overlay {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(255, 255, 255, 0.9);display: flex;flex-direction: column;justify-content: center;align-items: center;z-index: 9999;
}
</style>

4.2 图片预览器

<!-- ImageViewer.vue -->
<template><teleport to="body"><divv-if="visible"class="image-viewer"@click="close"><img:src="imageUrl"@click.stop><div class="controls"><button @click.stop="prev">&lt;</button><button @click.stop="next">&gt;</button></div></div></teleport>
</template><script setup>
const props = defineProps({visible: Boolean,imageUrl: String,images: Array
})const emit = defineEmits(['update:visible'])const close = () => {emit('update:visible', false)
}const prev = () => {// 实现上一张逻辑
}const next = () => {// 实现下一张逻辑
}
</script>

5. 最佳实践

5.1 目标元素管理

<!-- index.html -->
<!DOCTYPE html>
<html>
<head><title>Vue App</title>
</head>
<body><div id="app"></div><!-- 为 Teleport 预留的容器 --><div id="modals"></div><div id="notifications"></div><div id="tooltips"></div>
</body>
</html>

5.2 组件封装

<!-- BaseModal.vue -->
<template><teleport to="#modals"><transition name="modal"><divv-if="modelValue"class="modal-container"@click.self="close"><div class="modal-content"><slot></slot></div></div></transition></teleport>
</template><script setup>
defineProps({modelValue: Boolean
})const emit = defineEmits(['update:modelValue'])const close = () => {emit('update:modelValue', false)
}
</script>

6. 注意事项

  1. 目标元素存在性检查
<template><teleport to="#target" :disabled="!targetExists"><div>内容</div></teleport>
</template><script setup>
import { ref, onMounted } from 'vue'const targetExists = ref(false)onMounted(() => {targetExists.value = !!document.querySelector('#target')
})
</script>
  1. SSR 兼容性
<template><client-only><teleport to="body"><div>仅客户端渲染的内容</div></teleport></client-only>
</template>
  1. 清理工作
<script setup>
import { onUnmounted } from 'vue'onUnmounted(() => {// 确保清理所有传送的内容const target = document.querySelector('#target')if (target) {target.innerHTML = ''}
})
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/67149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用openwrt搭建ipsec隧道

背景&#xff1a;最近同事遇到了个ipsec问题&#xff0c;做的ipsec特性&#xff0c;ftp下载ipv6性能只有100kb, 正面定位该问题也蛮久了&#xff0c;项目没有用openwrt, 不过用了开源组件strongswan, 加密算法这些也是内核自带的&#xff0c;想着开源的不太可能有问题&#xff…

基于AnolisOS 8.6安装GmSSL 3.1.1及easy_gmssl库测试国密算法

测试环境 Virtual Box&#xff0c;AnolisOS-8.6-x86_64-minimal.iso&#xff0c;4 vCPU, 8G RAM, 60 vDisk。最小化安装。需联网。 系统环境 关闭防火墙 systemctl stop firewalld systemctl disable firewalld systemctl status firewalld selinux关闭 cat /etc/selinux/co…

HTML从入门到精通:链接与图像标签全解析

系列文章目录 01-从零开始学 HTML&#xff1a;构建网页的基本框架与技巧 02-HTML常见文本标签解析&#xff1a;从基础到进阶的全面指南 03-HTML从入门到精通&#xff1a;链接与图像标签全解析 文章目录 系列文章目录前言一、链接与图像标签&#xff08;HTML 标签基础&#xff…

[STM32 - 野火] - - - 固件库学习笔记 - - -十一.电源管理系统

一、电源管理系统简介 电源管理系统是STM32硬件设计和系统运行的基础&#xff0c;它不仅为芯片本身提供稳定的电源&#xff0c;还通过多种电源管理功能优化功耗、延长电池寿命&#xff0c;并确保系统的可靠性和稳定性。 二、电源监控器 作用&#xff1a;保证STM32芯片工作在…

数字图像处理:实验六

uu们&#xff01;大家好&#xff0c;2025年的新年就要到来&#xff0c;咸鱼哥在这里祝大家在2025年每天开心快乐&#xff0c;天天挣大钱&#xff0c;自由自在&#xff0c;健健康康&#xff0c;万事如意&#xff01;&#xff08;要是咸鱼哥嘴笨的话&#xff0c;还望大家多多包涵…

Langchain+文心一言调用

import osfrom langchain_community.llms import QianfanLLMEndpointos.environ["QIANFAN_AK"] "" os.environ["QIANFAN_SK"] ""llm_wenxin QianfanLLMEndpoint()res llm_wenxin.invoke("中国国庆日是哪一天?") print(…

上海亚商投顾:沪指冲高回落 大金融板块全天强势 上海亚商投

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一&#xff0e;市场情绪 市场全天冲高回落&#xff0c;深成指、创业板指午后翻绿。大金融板块全天强势&#xff0c;天茂集团…

农产品价格报告爬虫使用说明

农产品价格报告爬虫使用说明 # ************************************************************************** # * * # * 农产品价格报告爬虫 …

3.4 Go函数作用域(标识符)

作用域标识符 简单来说&#xff0c;作用域指的是标识符可以起作用的范围&#xff0c;即其可见范围。将标识符的可见性限制在一定范围内&#xff0c;这个范围就是作用域。 把标识符约束在一定的可见范围内&#xff0c;这个范围就是作用域。 1. 宇宙块 特点&#xff1a;预定义…

kaggle比赛入门 - House Prices - Advanced Regression Techniques(第二部分)

本文承接上一篇 1. 分析住宅类型&#xff08;BldgType&#xff09;的分布以及它们与销售价格&#xff08;SalePrice&#xff09;的关系 # 1. distribution of dwelling types and their relation to sale prices # BldgType: Type of dwellingdwelling_types df[BldgType].v…

使用shell命令安装virtualbox的虚拟机并导出到vagrant的Box

0. 安装virtualbox and vagrant [rootolx79vagrant ~]# cat /etc/resolv.conf #search 114.114.114.114 nameserver 180.76.76.76-- install VirtualBox yum install oraclelinux-developer-release-* wget https://yum.oracle.com/RPM-GPG-KEY-oracle-ol7 -O /etc/pki/rpm-g…

【数据结构】空间复杂度

目录 一、引入空间复杂度的原因 二、空间复杂度的分析 ❥ 2.1 程序运行时内存大小 ~ 程序本身大小 ❥ 2.2 程序运行时内存大小 ~ 算法运行时内存大小 ❥ 2.3 算法运行时内存大小 ❥ 2.4 不考虑算法全部运行空间的原因 三、空间复杂度 ❥ 3.1空间复杂度的定义 ❥ 3.2 空…

MySQL--》深度解析InnoDB引擎的存储与事务机制

目录 InnoDB架构 事务原理 MVCC InnoDB架构 从MySQL5.5版本开始默认使用InnoDB存储引擎&#xff0c;它擅长进行事务处理&#xff0c;具有崩溃恢复的特性&#xff0c;在日常开发中使用非常广泛&#xff0c;其逻辑存储结构图如下所示&#xff0c; 下面是InnoDB架构图&#xf…

Redis高阶5-布隆过滤器

Redis布隆过滤器 ​ 由一个初始值都为零的bit数组和多个哈希函数构成&#xff0c;用来快速判断集合中是否存在某个元素 目的减少内存占用方式不保存数据信息&#xff0c;只是在内存中做一个是否存在的标记flag 布隆过滤器&#xff08;英语&#xff1a;Bloom Filter&#xff0…

DeepSeek学术题目选择效果怎么样?

论文选题 一篇出色的论文背后&#xff0c;必定有一个“智慧的选题”在撑腰。选题足够好文章就能顺利登上高水平期刊&#xff1b;选题不行再精彩的写作也只能“当花瓶”。然而许多宝子们常常忽视这个环节&#xff0c;把大量时间花在写作上&#xff0c;选题时却像抓阄一样随便挑一…

第五节 MATLAB命令

本节的内容将提供常用的一些MATLAB命令。 在之前的篇章中我们已经知道了MATLAB数值计算和数据可视化是一个交互式程序&#xff0c;在它的命令窗口中您可以在MATLAB提示符“>>”下键入命令。 MATLAB管理会话的命令 MATLAB提供管理会话的各种命令。如下表所示&#xff1a;…

Docker核心命令与Yocto项目的高效应用

随着软件开发逐渐向分布式和容器化方向演进&#xff0c;Docker 已成为主流的容器化技术之一。它通过标准化的环境配置、资源隔离和高效的部署流程&#xff0c;大幅提高了开发和构建效率。Yocto 项目作为嵌入式 Linux 系统构建工具&#xff0c;与 Docker 的结合进一步增强了开发…

Qt 5.14.2 学习记录 —— 이십 QFile和多线程

文章目录 1、QFile1、打开2、读写3、关闭4、程序5、其它功能 2、多线程1、演示2、锁 3、条件变量和信号量 1、QFile Qt有自己的一套文件体系&#xff0c;不过Qt也可以使用C&#xff0c;C&#xff0c;Linux的文件操作。使用Qt的文件体系和Qt自己的一些类型更好配合。 管理写入读…

【全栈】SprintBoot+vue3迷你商城-扩展:vue3项目创建及目录介绍

【全栈】SprintBootvue3迷你商城-扩展&#xff1a;vue3项目创建及目录介绍 往期的文章都在这里啦&#xff0c;大家有兴趣可以看一下 【全栈】SprintBootvue3迷你商城&#xff08;1&#xff09; 【全栈】SprintBootvue3迷你商城&#xff08;2&#xff09; 【全栈】SprintBootvu…

使用Aardio库在Python中创建桌面应用:简单指南

引言 随着软件开发需求的不断增长&#xff0c;开发者们需要更加灵活和高效的工具来快速构建应用程序。Python以其简洁易读的语法和强大的社区支持而闻名&#xff0c;但在创建图形用户界面&#xff08;GUI&#xff09;时&#xff0c;可能会遇到一些挑战。Aardio作为一种轻量级的…