当前位置: 首页 > news >正文

跨域场景下的Iframe事件监听

背景

在当前window窗口,对于一些浮窗组件,一般需要点击当前window下的其他位置才能够隐藏浮窗。但如果当前窗口中存在iframe区域,那么由于一些特殊的性质,无法通过常规的click点击事件监听iframe元素的点击,而通过contentDocument的形式也很难在跨域存在的情况下实现。

解决方案

window对象本身可以监听到blur方法,在点击到iframe时,会触发父级窗口的blur事件,此时可以间接监听到相当于点击到了iframe的事件。

缺陷

当然,缺陷很明显,其他方式触发了窗口的blur时,也会触发该事件,而不是点击到了iframe。但对于以上场景,是完全够用的。

代码

import { ref, onUnmounted, Ref } from 'vue';export function useIframeClick(iframeRef: Ref<HTMLIFrameElement | undefined>,handleIframeClick: () => void
) {// 监听iframe点击的状态const iframeClickDetection = ref({isSetup: false,blurTimer: null as NodeJS.Timeout | null,focusTimer: null as NodeJS.Timeout | null,});// 覆盖层相关状态const showClickOverlay = ref(false);const overlayTimer = ref<NodeJS.Timeout | null>(null);// 处理覆盖层点击const handleOverlayClick = () => {console.log('覆盖层检测到点击');handleIframeClick();// 点击后短暂隐藏覆盖层,让用户能正常与iframe交互showClickOverlay.value = false;setTimeout(() => {showClickOverlay.value = true;}, 100);};// 鼠标进入覆盖层时暂时隐藏,允许正常交互const handleOverlayMouseEnter = () => {if (overlayTimer.value) {clearTimeout(overlayTimer.value);}overlayTimer.value = setTimeout(() => {showClickOverlay.value = false;}, 500); // 500ms后隐藏};// 鼠标离开后重新显示覆盖层const handleOverlayMouseLeave = () => {if (overlayTimer.value) {clearTimeout(overlayTimer.value);}overlayTimer.value = setTimeout(() => {showClickOverlay.value = true;}, 1000); // 1s后重新显示};// 设置iframe点击检测const setupIframeClickDetection = () => {if (iframeClickDetection.value.isSetup) return;const detection = iframeClickDetection.value;// 监听window的焦点事件const handleWindowBlur = () => {// 延迟检测,确保是iframe获得了焦点detection.blurTimer = setTimeout(() => {// 检查当前活动元素是否是iframeif (document.activeElement === iframeRef.value) {handleIframeClick();}}, 0);};const handleWindowFocus = () => {// 清除blur定时器if (detection.blurTimer) {clearTimeout(detection.blurTimer);detection.blurTimer = null;}};// 监听鼠标移动事件,确保是真实的点击而不是键盘导航let mouseMovedOverIframe = false;const handleMouseMove = (e: MouseEvent) => {const iframeRect = iframeRef.value?.getBoundingClientRect();if (iframeRect) {const isOverIframe =e.clientX >= iframeRect.left &&e.clientX <= iframeRect.right &&e.clientY >= iframeRect.top &&e.clientY <= iframeRect.bottom;mouseMovedOverIframe = isOverIframe;}};// 改进的blur处理const handleWindowBlurImproved = () => {detection.blurTimer = setTimeout(() => {if (document.activeElement === iframeRef.value && mouseMovedOverIframe) {handleIframeClick();}}, 0);};window.addEventListener('blur', handleWindowBlurImproved);window.addEventListener('focus', handleWindowFocus);document.addEventListener('mousemove', handleMouseMove);detection.isSetup = true;// 清理函数onUnmounted(() => {window.removeEventListener('blur', handleWindowBlurImproved);window.removeEventListener('focus', handleWindowFocus);document.removeEventListener('mousemove', handleMouseMove);if (detection.blurTimer) {clearTimeout(detection.blurTimer);}});};return {showClickOverlay,setupIframeClickDetection,handleOverlayClick,handleOverlayMouseEnter,handleOverlayMouseLeave,};
}

http://www.dtcms.com/a/316818.html

相关文章:

  • 【机器学习深度学习】模型量化
  • OSPF作业
  • Linux 基础
  • vue3 计算方式
  • GPS信号捕获尝试(上)
  • 【android bluetooth 协议分析 01】【HCI 层介绍 30】【hci_event和le_meta_event如何上报到btu层】
  • 【三个数公因数】2022-10-7
  • MySQL CONV()函数
  • 永磁同步电机无速度算法--基于二自由度结构的反推观测器TSBO
  • JAVA学习笔记 自增与自减的使用-006
  • 哲学中的主体性:历史演进、理论范式与当代重构
  • 【Unity】背包系统 + 物品窗口管理系统(中)
  • RC和RR的区别
  • Pytorch实现婴儿哭声检测和识别
  • 【web自动化测试】实战
  • Coze Studio开源,企业用户多了一种选择,也需多几分考量
  • 如何通过 5 种方式将照片从 iPad 传输到电脑
  • 埋点技术进阶:如何构建高效的数据采集架构
  • 默认二级路由(React-Router 6)
  • linux-系统日志查看指令systemctl
  • 《方块34:金花之渊》
  • Linux 常用命令大全
  • C++ 拷贝赋值、swap 与 noexcept 深度解析:高效实现 operator=
  • 工业数采引擎-通信链路SOCKET
  • Python高级编程与实践:Python网络编程基础与实践
  • Linux的NFS与Autofs配置指南
  • mac安装pycharm
  • 2048小游戏
  • VUE2 学习笔记 合集
  • 如何在nuxt项目中使用axios进行网络请求?