postMessage到底有多好用

postMessage是什么?

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

Html5中的postMessage解决跨域,跨窗口消息传递

postMessage的优点

  1. 两个跨域页面的消息传递
  2. 多窗口之间的消息传递
  3. 嵌套iframe的数据传递
postMessage()

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。 postMessage(data,origin)方法接受两个参数

  1. data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。
  2. origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

例如:

// A页面 [http://a.com]
const data = document.getElementById('name').value;
window.frames[0].postMessage(data,'http://b.com');
复制代码

在B页面监听message事件,获取传递过来的数据

// B页面 [http://b.com]
window.addEventListener('message', function(ev) {
    // 当我们是父子窗口进行消息传递时,可以使用此判断,只接受父窗口传递来的消息,
    if (ev.source !== window.parent) return;
    var data = ev.data;
    console.info('message from parent:', data);
}, false);
复制代码

通过这样的一个传递和接受的过程可以实现一个完整的消息传递。不管A,B是否跨域,是否存在嵌套关系,都可以使用postMessage的方式实现消息传递。

MessageEvent的属性
  • data:从源端传递来的message
  • source:发送消息的窗口对象
  • origin:发送消息窗口的源(协议+主机+端口号)

当我们只处理某些源发送过来的消息时,我们可以使用origin来做判断,只处理某一些源的message,这样方便过滤一些不必要的值。

解决问题

最近遇到一个问题,自己的代码【A_child】是通过Iframe的方式放在A系统中的,因为代码中需要A系统登录时的用户信息去获取资源,所以需要A系统中的cookie信息。目前的处理方式就是讲我的代码部署到A系统的服务器上,然后指定不同的端口,这样使用嵌入iframe的方式实现cookie共享。但是缺点就是每次更新代码都需要A系统的负责人去做更新。耗费了大量的人力和时间成本。

注意:相同的域名,不同的端口可以共享cookie信息。

最近为了减轻自己的工作负担,决定写一个中间层页面,放在A系统下,菜单的指向不变,只是在中间层的页面中在做一次iframe嵌套,并且在这个页面中将A系统中的cookie信息使用postMessage的方式发送给origin端。

注意:因为我自己代码进入时就需要带着用户信息请求表格数据,所以页面的所有操作必须在收到message后才进行。所以就有了下面的这个代码

window.addEventListener('message', (ev) => {
    if (ev.source !== window.parent) return;
    const data = ev.data; 
    ...
    ...
    ...
    Vue.prototype.userInfo = data;
    new Vue({
        el: '#app',
        router,
        store,
        render: h => h(renderComponents),
    });
}, false);
复制代码
当然解决嵌套iframe跨域传值的问题,还有另外的两个方法。
  1. 使用hash值,将需要传递的值data放在iframe中src的hash中。
  2. 子页面传值给父页面,可以借助C页面【C和A必须时同域的】,A中嵌套B,B中嵌套C,B要想A传值,可以使用C作为一个事件BUS,B中的数据先传递给C,然后在通过C传递数据给A。【此方法筱筱没用过啊】,大概方法是这样的。
总结

html5新增的特性,postMessge主要是更方便的解决了多页面的消息传递,并且有效解决了跨域问题。使用起来更加的简单方便。不过根据自己的需求选择不同的处理方式。

欢迎关注微信公众号

转载于:https://juejin.im/post/5c3efccef265da61290a6a3e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值