Js前端解决方案:
1、片段识别符(fragment identifier)
2、跨文档通信API(Cross-document messaging)- window.postMessage()
片段标识符
片段标识符指的是URL # 号后面的部分
比如http://example.com/xxx.html#flag的flag;改变片段标识符,页面不会刷新
父窗口改变子窗口的URL
// 父窗口改变子窗口的URL
var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;
// 子窗口绑定onhashchange方法,url改变会触发onhashchange方法
window.onhashchange = checkMessage;
function checkMessage() {
var message = window.location.hash;
// 执行操作
}
子窗口改变父窗口的URL
// 子窗口改变父窗口类似
parent.location.href = target + '#' + hash;
跨文档通信API -> window.postMessage()
window.postMessage(参数1,参数2)
参数1:具体的信息内容
参数2:窗口的源(协议 + 域名 + 端口 / *代表所有窗口)
父窗口向子窗口发送信息
父窗口:http://parent.com 子窗口:http://child.com
// 父窗口打开一个子窗口
var popup = window.open('http://child.com', 'title');
// 父窗口向子窗口发消息
popup.postMessage('Hello World!', 'http://child.com');
子窗口向父窗口发送信息
// 子窗口向父窗口发消息
window.opener.postMessage('Nice to see you', 'http://parent.com');
父子窗口监听messag事件来获取信息
// 父窗口和子窗口都可以用下面的代码,
// 监听 message 消息
window.addEventListener('message', function (event) {
if (event.origin !== 'http://parent.com') return;// 消息发向的网址:可以过滤不是发给父窗口的消息
if (event.origin !== 'http://child.com') return;// 消息发向的网址:可以过滤不是发给子窗口的消息
if (event.data === 'Hello World') {
event.source.postMessage('Hello', event.origin);// 发送消息
} else {
console.log(event.data);// 消息内容
}
},false);
注:
1、需要过滤信息的来源,不然任意网址发来的信息都会被处理
2、postMessage方法中指定的目标窗口的网址如果是一个星号,表示该信息可以向任意网址发送(一般不建议这样做)
message事件参数是事件对象event,有上面三个属性source、origin、data
- event.source:拿到发送消息的窗口
- event.origin:消息发向的网址
- event.data:消息内容
样例:父窗口向子窗口存入对象和读取对象
// 子窗口
window.onmessage = function(e) {
// 如果不是发给子窗口的过滤
if (e.origin !== 'http://child.com') return;
// 拿到发过来的信息e.data
var payload = JSON.parse(e.data);
switch (payload.method) {
case 'set':
localStorage.setItem(payload.key, JSON.stringify(payload.data));
break;
case 'get':
var parent = window.parent;
var data = localStorage.getItem(payload.key);
parent.postMessage(data, 'http://parent.com');
break;
case 'remove':
localStorage.removeItem(payload.key);
break;
}
};
// 父窗口
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
// 存入对象
win.postMessage(
JSON.stringify({key: 'storage', method: 'set', data: obj}),
'http://child.com'
);
// 读取对象
win.postMessage(
JSON.stringify({key: 'storage', method: "get"}),
"*"
);
window.onmessage = function(e) {
// 如果不是发给父窗口的过滤
if (e.origin != 'http://parent.com') return;
console.log(JSON.parse(e.data).name);
};
参考文档:JavaScript教程 iframe和多窗口通信
遇到问题可以评论留言,欢迎一起讨论问题!