由iframe而引发的一系列思考(跨域通信)

前情提要:公司的首页,有三个板块需要自定义,故以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");
}
原文地址:https://www.cnblogs.com/caofeng11/p/13775247.html