最近遇到一个项目,用了iframe嵌入了另一个项目作为内容区,两个项目之间需要进行信息传递,如果用window.top的话只支持同一个域,于是便想到了postMessage来进行跨域通信。
1.postMessage基本用法
【发送消息】
otherWindow.postMessage(message, targetOrigin, [transfer])
- otherWindow 要通信的window对象(即接收消息的窗口)
- message 传递的数据
- targetOrigin 目标窗口的源(如果为*,可以为任何窗口传递信息)
【接收消息】
window.addEventListener('message', function (e) { console.log(e.data) //e.data为传递过来的数据 console.log(e.origin) //e.origin为调用 postMessage 时消息发送方窗口的 origin(域名、协议和端口) console.log(e.source) //e.source为对发送消息的窗口对象的引用,可以使用此来在具有不同origin的两个窗口之间建立双向通信 })
先说明一下框架结构:
<!--项目地址: http://aaa.com/a.html-->
<!--A区--> <div> <!--B区--> <iframe src="http://bbb.com/a.html"> <!--c区--> <iframe src="./b.html"></iframe> </iframe> </div>
注:下文会用ABC区来表示框架当前区域
【A → B → C】
A区:
$(document).ready(function(){ window.addEventListener('scroll', function(){ var top = document.body.scrollTop || document.documentElement.scrollTop; var clientH = document.documentElement.clientHeight || document.body.clientHeight; var iframe = document.getElementById('iframe'); iframe.contentWindow.postMessage({type: 'scrollpx', data: top, clientH: clientH}, *); }, false) })
B区:
<input id="scrollpx" hidden />
$(document).ready(function(){ window.removeEventListener('message', function(){},null) window.addEventListener('message', function(e){ if(e.data.type==='scrollpx'){ $('#scrollpx').attr('clienth', e.data.clientH).val(ed.ata.data); $('#scrollpx').trigger('input'); } }) })
注:A区不能直接传数据至C,唯有曲线救国先传到B,再传至C(把传递到到数据赋值给B区隐藏到input,在C区监听B区input的到变化)。
C区:
parent.$('#scrollpx').bind('input propertychange', function(){ var top = parseInt($(this).val()); $(xx).css('top', top+'px'); })
注:$(xx).change(function(){}必须有失焦过程才能触发,所以得改成上面的触发方式方能监听。
【C → A】
C区:
$(xx).on('click', function(){ top.postMessage({ type: 'aaa', data: 200 }, '*') });
A区:
$(document).ready(function(){ window.addEventListener('message', function(e){ if(e.data.type==='aaa'){ window.scrollTo(0, e.data.data); } }) })
鄙人不才,欢迎补充。