【vue与iframe通讯】

vue 与 iframe 通讯

  • 发送数据
    • vue 向 iframe 发送数据
    • iframe 向 vue 发送数据
    • 接收信息( vue & iframe 通用)
  • 实现相互通讯
    • 通讯流程图
    • 实现代码
      • vue 页面
      • iframe页面
      • `iframe`内部重定向访问地址,更新`vue`路由
  • 代码下载

前言:vue嵌套iframe实现步骤

发送数据

vue 向 iframe 发送数据

	// utils/common.js
 
	/** vue向iframe发送数据
	  * content iframe.contentWindow
	  * type 事件类型
	  * data 传送的数据
	  */
	export function sendPostMessage(content, type, data = {}) {
		content.postMessage({ type, data }, '*');
	}

iframe 向 vue 发送数据

 // update.html & base.html & includes.html ...
 
 function sendPostMessage(type, data = {}) {
     window.parent.postMessage({ type, data }, "*");
 }

接收信息( vue & iframe 通用)

  // utils/iframe-message.js
  
  /**
   * 接收页面 postMessage 发送的信息
   * Pubsub提供多种类型供订阅,使用方法如下:
   * 1. 需要接收webSocket的地方,import eventsPub from '本文件路径'
   * 2. eventsPub.on(类型, callback)
   *    例:
   *      const receive = data => console.log('eventName', data)
   *      eventsPub.on('eventName', receive)
   * 3.不需要继续接收时调用
   *    eventsPub.remove("eventName", receive) 移除callback
   */

  /** 重要: postMessageEvent 中的 type 需提前定义 */
  class PubSub {
    list = {};
    constructor(events) {
      this.list = {};
      events.forEach(v => {
        this.list[v] = [];
      });
    }

    on(ev, callback) {
      if (this.list[ev]) {
        this.list[ev].push(callback);
        return true;
      } else {
        return false;
      }
    }

    emit(ev, data) {
      // data拷贝: 防止其他callback修改data
      const dataStr = JSON.stringify(data);
      if (this.list[ev]) {
        this.list[ev].forEach((v) => {
          try {
            v(JSON.parse(dataStr));
          } catch (err) {
            console.log("callback error:", err, v);
          }
        });
        return true;
      } else {
        return false;
      }
    }

    remove(ev, callback) {
      if (callback && this.list[ev]) {
        this.list[ev].forEach((v, i) => {
          if (v === callback) {
            this.list[ev].splice(i, 1);
          }
        });
        return true;
      } else {
        return false;
      }
    }
  }
  // 订阅的类型需要在postMessageEvent中提前定义好
  const postMessageEvent = ["PAGE_ISREADY"]
  const eventsPub = new PubSub(postMessageEvent);
  window.addEventListener("message", function (e) {
    if (e.data?.type) {
      eventsPub.emit(e.data.type, e.data.data)
    }
  });

  export default eventsPub;

实现相互通讯

通讯流程图

vue路由更新 及 iframe地址刷新时,两者之间的通讯流程
流程图

实现代码

vue 页面

  // IframeTemplate.vue
  
  import { onMounted, onBeforeUnmount } from "vue";
  import eventsPub from "@utils/iframe-message.js"
  import { sendPostMessage } from "@utils/common.js"

  onMounted(() => {
    // 接收信息
    eventsPub.on("PAGE_ISREADY", pageIsReady)
  });

  onBeforeUnmount(() => {
    eventsPub.remove("PAGE_ISREADY", pageIsReady)
  });

  function pageIsReady() {
      // console.log("PAGE_ISREADY")
      updateIframeLoginInfo()
  }

  // 发送信息
  /** iframe 页面登录信息同步 */
  function updateIframeLoginInfo() {
    const iframeWindow = $("#common-iframe")[0].contentWindow
    sendPostMessage(iframeWindow, "LOGIN_INFO", {
      token: localStorage.getItem("TOKEN"),
      userInfo: localStorage.getItem("USER") || "{}"
    })
  }

iframe页面

	// utils/iframe-message.js
	  
	// 将该文件写成原生写法: 删除 remove 之后的代码
	// 添加下边的代码
	
	/** 创建消息接收实例 */
	const postMessageEvent = ["LOGIN_INFO"]
	const eventsPub = new PubSub(postMessageEvent);
	
	/** 接收父页面的消息 */
	window.addEventListener("message", function (e) {
		if (e.data?.type) {
			eventsPub.emit(e.data.type, e.data.data)
		}
	});
	
	/** 发送消息 */
	function sendPostMessage(type, data = {}) {
		window.parent.postMessage({ type, data }, "*");
	}
  // base.html、includes.html、update.html...
  
  // 在所有的页面中引入iframe-message.js、jquery.js
  <script type="text/javascript" src="./js/jquery.js"></script>
  <script type="text/javascript" src="./js/iframe-message.js"></script>
  // 并添加下边的代码
  <script type="text/javascript">

    /** 获取当前登录用户信息并存储 */
    function setUserInfo(data) {
      const { token, userInfo } = data;
      const curToken = localStorage.getItem("TOKEN")
      const curUser = localStorage.getItem("USER")
      curToken != token && localStorage.setItem("TOKEN", token)
      curUser != userInfo && localStorage.setItem("USER", userInfo)
    }

    $(document).ready(() => {
      // GET VUE MESSAGE
      eventsPub.on("LOGIN_INFO", setUserInfo)

      // NOTIFY VUE MESSAGE
      sendPostMessage("PAGE_ISREADY", { iframeIsReady: true })
    })
  </script>

iframe内部重定向访问地址,更新vue路由

需将iframe的地址添加到vue路由上

  1. iframe页面判断是否是内部跳转,并将页面地址发送到vue

        // base.html...
        
        function setUserInfo(data) {
            // 其他...
            localStorage.setItem("FROM_PARENT", true)
        }
        $(document).ready(() => {
            // 其他...
            /** iframe内部页面跳转,加载完成 -  */
            const fromParent = localStorage.getItem("FROM_PARENT")
            localStorage.removeItem("FROM_PARENT")
            // 判断是否是vue 页面重定向的
            const { pathname, href, search } = window.location
            let path = pathname.split(".")[0];
            sendPostMessage("PAGE_ISREADY", !fromParent ? {} : { path })
        })
        ```
    
    
  2. vue 接收到地址后,页面路由修改,但iframe页面不需要再刷新

        // IframeTemplate.vue
        
        // 监听路由变更
        watch(route, () => {
          const historyParams = history.state.params
          // 只更新路由时,iframe 页面地址不更新
          if (historyParams && historyParams.justRoute && isFrameSrcUpdate == route.path && !isMounted) {
            isFrameSrcUpdate = "";
            return;
          }
          // iframe 页面地址更新
          createIframe()
        });
        
        /** iframe 页面加载完毕
         * 1. 登陆信息同步
         * 2. iframe 内部跳转,页面地址变化后,vue route也修改(但页面不刷新)
         */
        function pageIsReady(data) {
          updateIframeLoginInfo()
          if (data?.path) {
            let { path, name, query } = data
            isFrameSrcUpdate = path;
            const exit = router.getRoutes().find(i => i.path == path)
            /** iframe 发送了一个未添加路由的页面
             *  1. 添加该页面路由,为能正常访问
             *  2. 在当前页面刷新后,会有路由不存在的问题,
             *    需在整体添加路由的位置将当前页面添加进进去
             */
            !exit && router.addRoute({
              path,
              name,
              meta: { isIframe: true },
              component: () => import("../views/IframePage.vue")
            })
            // justRoute:只更新路由,不刷新页面
            router.push({ path, query, state: { params: { justRoute: true } } });
          }
        }
    

代码下载

查看代码地址

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回溯算法05(leetcode491/46/47)

参考资料&#xff1a; https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 491. 非递减子序列 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素…

微软开发者大会:编程进入自然语言时代、“AI员工”闪亮登场

当地时间周二&#xff0c;美国科技公司微软召开年度Build开发者大会。在CEO纳德拉的带领下&#xff0c;微软各个产品团队再一次展现出惊人的执行力&#xff0c;在发布会上又拿出了接近50个新产品或功能更新。 整场发布会持续了接近两个小时&#xff0c;在这里挑选了一些投资者…

知识表示概述

文章目录 知识表示研究现状技术发展趋势 知识表示 知识是人类在认识和改造客观世界的过程中总结出的客观事实、概念、定理和公理的集合。知识具有不同的分类方式&#xff0c;例如按照知识的作用范围可分为常识性知识与领域性知识。知识表示是将现实世界中存在的知识转换成计算机…

Linux进程的地址空间

Linux进程的地址空间 1. 前言 在编写程序语言的代码时&#xff0c;打印输出一个变量的地址时&#xff0c;这个地址在内存中是以什么形式存在的&#xff1f;一个地址可以存储两个不同的值吗&#xff1f; 运行以下代码&#xff1a; #include <stdio.h> #include <un…

C#-根据日志等级进行日志的过滤输出

文章速览 概要具体实施创建Log系统动态修改日志等级 坚持记录实属不易&#xff0c;希望友善多金的码友能够随手点一个赞。 共同创建氛围更加良好的开发者社区&#xff01; 谢谢~ 概要 方便后期对软件进行维护&#xff0c;需要在一些关键处添加log日志输出&#xff0c;但时间长…

vulhub——ActiveMQ漏洞

文章目录 一、CVE-2015-5254(反序列化漏洞)二、CVE-2016-3088&#xff08;任意文件写入漏洞&#xff09;2.1 漏洞原理2.2 写入webshell2.3 写入crontab 三、CVE-2022-41678&#xff08;远程代码执行漏洞&#xff09;方法一方法2 四、CVE-2023-46604&#xff08;反序列化命令执行…

HTML+CSS+JS 扩散登录表单动画

效果演示 Code <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,us…

MAIA:多模态自动化可解释智能体的突破

随着人工智能技术的飞速发展&#xff0c;深度学习模型在图像识别、自然语言处理等领域取得了显著成就。然而&#xff0c;这些模型的“黑箱”特性使得其决策过程难以理解&#xff0c;限制了它们的应用范围和可靠性。为了解决这一问题&#xff0c;研究者们提出了多种模型可解释性…

【机器学习】—机器学习和NLP预训练模型探索之旅

目录 一.预训练模型的基本概念 1.BERT模型 2 .GPT模型 二、预训练模型的应用 1.文本分类 使用BERT进行文本分类 2. 问答系统 使用BERT进行问答 三、预训练模型的优化 1.模型压缩 1.1 剪枝 权重剪枝 2.模型量化 2.1 定点量化 使用PyTorch进行定点量化 3. 知识蒸馏…

[emailprotected](7)父子通信,传递元素内容

目录 1&#xff0c;children 属性2&#xff0c;多个属性 普通对象等&#xff0c;可以通过变量直接传递&#xff0c;那类似 vue 中的 slot 插槽&#xff0c;如何传递元素内容&#xff1f; 1&#xff0c;children 属性 实际上&#xff0c;写在自定义组件标签的内部代码&#xf…

【再探】Java—泛型

Java 泛型本质是参数化类型&#xff0c;可以用在类、接口和方法的创建中。 1 “擦除式”泛型 Java的“擦除式”的泛型实现一直受到开发者的诟病。 “擦除式”的实现几乎只需要在Javac编译器上做出改进即可&#xff0c;不要改动字节码、虚拟机&#xff0c;也保证了以前没有使…

k8s pv 一直是release状态

如下图所示&#xff0c;pv 一直是release状态 这个时候大家可能就会想到现在我的 PVC 被删除了&#xff0c;PV 也变成了 Released 状态&#xff0c;那么我重建之前的 PVC 他们不就可以重新绑定了&#xff0c;事实并不会&#xff0c;PVC 只能和 Available 状态的 PV 进行绑定。…

【华为】将eNSP导入CRT,并解决不能敲Tab问题

华为】将eNSP导入CRT&#xff0c;并解决不能敲Tab问题 eNSP导入CRT打开eNSP&#xff0c;新建一个拓扑右键启动查看串口号关联CRT成功界面 SecureCRT连接华为模拟器ensp,Tab键不能补全问题选择Options&#xff08;选项&#xff09;-- Global Options &#xff08;全局选项&#…

ORB-SLAM2从理论到代码实现(六):Tracking程序详解(上)

1. Tracking框架 Tracking线程流程框图&#xff1a; 各流程对应的主要函数 2. Tracking整体流程图 上面这张图把Tracking.cc讲的特别明白。 tracking线程在获取图像数据后&#xff0c;会传给函数GrabImageStereo、GrabImageRGBD或GrabImageMonocular进行预处理&#xff0c;这…

wordpress主题 ACG美化插件v3.4.2支持zibll主题7b2主题美化

独具一格的二次元风格&#xff0c;打造全新的子比美化方向 大部分代码均为CSS、JS做成插件只是为了方便懒人小白站长 后台全功能一览&#xff0c;大部分美化均为网上通用流传&#xff0c;

基于ucos-ii操作系统的生产者消费者-问题

目 录 第1章 题目分析. 1 1.1 生产者线程... 1 1.2 消费者线程... 1 1.3 缓冲区... 1 1.4 进程的同步与互斥... 1 第2章 解决方案. 2 2.1 总体方案... 2 2.2 生产者问题... 2 2.3 消费者问题... 3 2.4 进程问题... 5 第3章 实验结果. 6 3.1 运行结果... 6 3.2 结果分析... 8 第…

用kimi一键绘制《庆余年》人物关系图谱

《庆余年》里面人物关系复杂&#xff0c;如果能画出一个人物关系图谱&#xff0c;可以直观的理解其中人物关系&#xff0c;更好的追剧。 首先&#xff0c;用kimi下载庆余年的分集剧情&#xff0c;常见文章《AI网络爬虫&#xff1a;批量爬取电视猫上面的《庆余年》分集剧情》&am…

【Java面试】三、Redis篇(下)

文章目录 1、抢券场景2、Redis分布式锁3、Redisson实现分布式锁4、Redisson实现的分布式锁是可重入锁5、Redisson实现分布式锁下的主从一致性6、面试 1、抢券场景 正常思路&#xff1a; 代码实现&#xff1a; 比如优惠券数量为1。正常情况下&#xff1a;用户A的请求过来&a…

Centos7.9上安装Oracle 11gR2 RAC 三节点(ASMlib管理asm磁盘)

服务器规划 OS 规格 主机名 IP VIP private IP scanip centos 7.9 1C4G racdb01 192.168.40.165 192.168.183.165 192.168.40.16 192.168.40.200 centos 7.9 1C4G racdb02 192.168.40.175 192.168.183.175 192.168.40.17 192.168.40.200 centos 7.9 1C4G…

目前流行的前端框架有哪些?

目前流行的前端框架有很多&#xff0c;它们可以帮助开发者快速构建高质量的前端应用程序。本文将介绍一些目前比较受欢迎的前端框架&#xff0c;并分析它们的优缺点。 React React 是一个由 Facebook 开发的开源前端JavaScript库&#xff0c;用于构建用户界面&#xff0c;尤其…