iframe是一种在网页中嵌入其他网页或文档的标签,虽然它在某些情况下可以提供一些便利,但也存在一些缺点需要考虑:
为了避免以上问题,可以考虑以下解决方案:
① 父页面监听iframe消息:
window.addEventListener('message', receiveMessageIframePage, false);
② 父页面发送给iframe页面的消息:
iframe.contentWindow.postMessage({ type: 'boundFileKeys', data: "消息内容体" }, '*');
③ iframe页面监听父页面发过来的消息:
window.addEventListener('message', onMessage, false);
④ iframe页面给父页面发送消息:
window.parent.postMessage({ type: 'check', data: ["自定义需要发送的数据"] }, '*');
iframe同源时,通过window.parent, window.top,等API就可以调用调用层的信息。通过window.top !== window.self,可以判断自身是否是最外层。
1、iframe跨域时,iframe组件之间常用的通信,主要是H5的possmessage方法,
发送信息的postMessage方法是向外界窗口发送信息
otherWindow.postMessage(message,targetOrigin);
otherWindow指的是目标窗口,也就是要给哪一个window发送消息,是window.frames属性的成员或者是window.open方法创建的窗口。 Message是要发送的消息,类型为String,Object(IE8、9不支持Obj),targetOrigin是限定消息接受范围,不限制就用星号 *
var onmessage = function(event) {
var data = event.data;
var origin = event.origin;
}
if(typeof window.addEventListener != 'undefined'){
window.addEventListener('message',onmessage,false);
}else if(typeof window.attachEvent != 'undefined'){
window.attachEvent('onmessage', onmessage);
}
a.html(http://www.nealyang.cn/a.html)
<iframe id="iframe" src="http://www.neal.cn/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var data = {
name: 'aym'
};
// 向neal传送跨域数据
iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.neal.cn');
};
// 接受domain2返回数据
window.addEventListener('message', function(e) {
alert('data from neal ---> ' + e.data);
}, false);
</script>
b.html(http://www.neal.cn/b.html)
<script>
// 接收domain1的数据
window.addEventListener('message', function(e) {
alert('data from nealyang ---> ' + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// 处理后再发回nealyang
window.parent.postMessage(JSON.stringify(data), 'http://www.nealyang.cn');
}
}, false);
</script>
2、当外层组件或者父组件的addEventListener方式不便于修改时(例如是比较旧的项目),也可以通过window.top进行一些另类的操作,下图1是打印出来的iframe里面打印出来的window.top,图2是控制台打印的window.top,可以看iframe里面获取window.top能拿到的信息是有限的。
项目中遇到一个问题,就是里面登录失效,会清除token,可是外层无法实时监听到token的失效,没有调转会登录页面,需要刷新才可以。但是实际内部又调用不到外层的reload方法。这里可以通过replace方式进行替代,通过环境变量配置不同环境下的登录地址,然后通过window.top.location.replace()进行路由刷新
/**
* 退出登录
*/
export function logout() {
if (cookies.get(config.MAS_TGC)) {
clearStorage();
}
console.log(config.escmLogin, 'config.escmLogin');
if (window.top !== window.self) {
window.top.location.replace(config.escmLogin);
} else {
window.location.href = config.singlePointLogin + window.location.origin + '/' + window.location.hash; // 退出登录时去掉ticket
}
}
跨域解决