前情提要:公司的首页,有三个板块需要自定义,故以iframe开发的形式给到第三方,第三方只要提供url给到父页面,即可实现板块的随意定制,并与父页面部分脱离(一定程度上还不能完全脱离父页面的联系,下文会细说)
问题起因:iframe的高度由子页面的高度决定,即子页面撑起iframe的高度,非iframe定宽,适用子页面内容动态不固定的情况,此场景需要获取子页面的高度,动态赋值iframe的height
情况一:父页面的地址与iframe的地址origin相同,即协议、域名、端口相同,此情况不存在跨域问题,可直接操作dom
// 同源非跨域,父级页面获取子级页面的高度赋值iframe
function setIframeHeight(id){ try{ var iframe = document.getElementById(id); if(iframe.attachEvent){ iframe.attachEvent("onload", function(){ iframe.height = iframe.contentWindow.document.documentElement.scrollHeight; // iframe.contentWindow,获取iframe的window对象 }); return; }else{ iframe.onload = function(){ iframe.height = iframe.contentDocument.body.scrollHeight; // iframe.contentDocument, 获取iframe的document对象 }; return; } }catch(e){ throw new Error('setIframeHeight Error'); } }
情况二:父页面与子页面的url地址,存在部分域相同,即aaa.xxx.com与bbb.xxx.com二级域名相同,但浏览器同源限制,父子页面相互dom操作,会跨域
需要将父子两个页面都设置domain,如:document.domain = "xxx.com",这样两个页面就可以操作了,实现了同一基础域名的跨域,设置domain后获取高度的方案就可以用上述同源非跨域的解决方案。 利用document.domain实现跨域的前提条件:这两个域名必须属于同一个基础域名(必须包含一个‘.’号),且所用的协议,端口都要一致
情况三:父页面与子页面的url地址,完全不相同,则可以使用CDM(cross document message)实现跨文本文档、多窗口、跨域消息传递,该方法兼容相ie8+
发送消息:targetWindow.postMessage(message,targetOrigin,[transfer]);
targetWindow指要接受消息的窗口;
message需要传递的消息内容,通常是字符串,若是对象,需要JSON.stringify转化
targetOrigin接受消息的域名,‘*’表示任意域名,‘/’表示传递给同域域名
接受消息:window.addEventListener('message',function(event){})
event.data从其他窗口传递来的数据,调用postMessage的message
event.origin发送消息窗口的origin,即targetWindow. origin
event.source发送消息窗口的引用,可以使用此在两个窗口之间建立双向通信
详细API:https://www.w3cschool.cn/fetch_api/fetch_api-lx142x8t.html
假设在a.html
里嵌套个<iframe src="http://www.b.com/b.html"></iframe>
,在这两个页面里互相通信
// a.html window.onload = function() { // a向b发送消息 window.frames[0].postMessage("data","http://www.b.com/b.html");
// a接受b发来的消息 window.addEventListener("message", function(event) { alert(event.data); });
}
// b.html window.onload = function() {
// b接受a发来的消息 window.addEventListener("message", function(event) { alert(event.data); });
// b向a发送消息 window.parent.postMessage("a需要的数据", "http://www.a.com/a.html");
}