认识iframe和window.postMessage的使用

起因是看到有赞技术博客里的这篇文章,有赞美业店铺装修前端解决方案
里面讲解了他们是如何实现店铺装修前端的架构,其中的模块和设计思想很值得一读(✪ω✪)。其中的这个关于pc页面和h5页面的思想,用到了iframe和postMessage的思想,感觉也是非常巧妙,利用这些做到了页面代码的复用,减少了重复造轮子的问题。

由于对于iframe接触的非常少,那还是先去了解一下原理和内容,再仔细看文章里的实现吧。

mdn里关于window.postMessage链接:window.postMessage

上述链接已经讲得很仔细了,不再做过多的重复。

值得注意的一点是:

otherWindow.postMessage(message, targetOrigin, [transfer])中,

第一个参数:message

在 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)之前, 参数 message 必须是一个字符串。 从 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,参数 message被使用结构化克隆算法进行序列化。这意味着您可以将各种各样的数据对象安全地传递到目标窗口,而不必自己序列化它们。**

所以,一般来说不做兼容浏览器的处理时,我们现在可以传 各种各样的数据对象,而不是只能传递字符串

自己写个测试的Demo例子吧,如何在一个名叫A.html里面使用iframe,嵌入另一个html叫B。在A.html发送消息给B,B的页面接收到发送的消息,显示出来。同时B也可以使用 window.postMessage发送消息给A。这样就实现了不太页面消息的传递

这里的例子主要参考的是这篇文章:使用 postMessage 解决 iframe 跨域通信问题

  • 首先来看A.html
<body style="border: 5px solid red;">
  <h1>this is A</h1>
 <iframe src="./B.html" id="myFrame"></iframe>
</body>
  • 再来看B.html
<body style="border: 5px solid yellow;">
  <h1>this is B</h1>
</body>

效果图如下:
效果图
  • 接下来再看如何让A发送消息给B,B接收到消息呢?
  const iframe = document.getElementById('myFrame');
  iframe.onload = function() {
    iframe.contentWindow.postMessage('A页面给你发消息啦~~','*');
  };

//以下是用来接收B页面发给A页面消息的逻辑
 window.addEventListener('message',receiveMessage,false);
 function receiveMessage(event) {
    console.log('A页面收到来自B的消息了==>',event)
  }
  • 接下来再B如何接收到A页面所发消息,并向A再发送一个消息?
 window.addEventListener('message',receiveMessage,false);
 function receiveMessage(event) {
    console.log('B页面收到来自A的消息了==>',event)
  }
  parent.postMessage('B页面也发送个消息给A页面你吧~','*');
  • 页面上打印的结果如下:
结果图

即这样我们就实现了不同源之间的交流。

那会到最开始有赞店铺装修的前端处理,如何让pc设计更新后,预览的h5页面使用同一套代码(实现跨端复用)呢,就是用了iframe和window.postMessage去处理。详细代码可参考链接,为了更好的理解,

画一个图了解一下:

类Messager的设计思路

那对应的h5如果做到复用一套代码呢?文章中是这么写的,

this.messager = new Messager(window.parent, `${window.location.protocol}//mei.youzan.com`);  
this.messager.on('pageChangeFromReact', (data) => {  
    ...
});

即打个比方,pc端做的事情:

pc端嵌入了iframe, 来源是h5的页面。pc每次绘制完毕或者点击完成或者保存时,都会

  • 在消息存储动作对象上,先去绑定绘制、完成、保存这些事件类型
  • 绑定完成后,在合适的节点去触发 由pc -> h5的一个事件消息发送,告诉h5:“h5渲染端 ,你好!我现在的事件类型是绘制更新完毕/点击完成/点击保存,要渲染的值是blabla...,我的地址是xxx”
  • 由于页面关闭或者一些其他原因,要去销毁这个事件监听器, 防止内存泄露(低版本的ie如果不手动销毁,可能会有问题)

敲黑板:

这里关于window.addEventListener的理解和解释,这篇文章写得很好: js添加事件和移除事件

对于h5端,它要做的事情:

  • 创建一个自己的messager实例,事件数据来源来自pc端。即h5现在拥有,Messager类里图中所画出的所有属性、值和方法

  • h5 在消息事件监听处理后,拿到从pc页面传来的消息,即h5: "啊哈哈,我收到消息了,现在的消息是blabla。。。",然后对消息进行解析渲染。

这样就可以利用iframe和postMessage,实现共用一份代码,实现更新。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 元素会创建包含另外一个文档的内联框架(即行内框架); 一、align 属性(不赞成) align属性规定ifram...
    puxiaotaoc阅读 19,974评论 0 14
  • 概述 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe...
    npmstart阅读 2,317评论 0 5
  • 来吧,少年,今天还能看文章学习的,一多半都是单身贵族,看朋友圈还会被虐,不如学习,上街还会被虐,不如学习,痛并快乐...
    范小饭_阅读 8,182评论 3 24
  • 什么是跨域 跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实...
    Yaoxue9阅读 1,423评论 0 6
  • 匆匆那年 ——献给末代师范生的记忆 八、殇逝 爱是天堂,亦是地狱。 第一次去上舞蹈课时,还没有舞蹈鞋,赤脚踩在木地...
    夏日树荫阅读 433评论 0 1

友情链接更多精彩内容