如何实现iframe父子传参通信
在最近的项目里面,用到了不少关于iframe父子传参通信的相关操作,记录一下,虽然很简单,但是确实十分有用的;
iframe通信可以分为2种,跨域和非跨域两种.分别说明;
有一点很重要,iframe是可以给name属性的;给上name属性可以省下一些代码;
非跨域父调子
//父页面点击 //子页面
父页面调用子页面使用childFrameName.window.fnName();;当然有一点很重要,你需要判断iframe里面的东西是否加载完成,如果加载未完成就调用的话是会报错的;
判断iframe加载是否完成有2种方法
1,childFrameName.document.readyState=="complete"来判断;
2,childFrameName.onload=function(){}使用onload回调函数,把调用的方法都写在这个回调函数里面;
非跨域子调父
//在父页面
同样的,在子页面调用父页面的方法使用parent.window.fnName()就可以了;
这种操作难免会遇到父页面获取子页面的元素,或者子页面获取父页面的元素进行操作;
非跨域父页面获取子页面元素操作
首先,我们有几种方法拿到子页面的window对象或者doucument对象,(还是使用上面的html)
//原生js获取子页面window对象 1,varchildWindow=document.getElementById("f").contentWindow; 2,varchildWindow=document.getElementsByTagName('f')[0].contentWindow; //其实也就是普通的获取方法,只是后面多了一个contentWindow; //jquery varchildWindow=$('#f').contentWindow; //获取子页面的document对象(假设已经通过上面的方法得到了window对象) varframeDoc=childWindow.document; varframeBody=frameDoc.body; //jquery也是跟上面的一样 varframeDoc=$(childWindow.document); //原生获取元素 childWindow.document.getElementById('a')//上面都已经拿到了子页面的window对象,所以获取子页面的元素也就只需要想普通操作那样获取就好 childWindow.document.getElementById('a').style.color='red'//改个颜色 //jq拿子页面元素 $('#f').contents().find('#a');//$('#f').contents这相当于拿到了iframe里面所有的dom;
非跨域子页面获取父页面元素
//原生js window.parent.document.getElementById('a');//window.parent获取到父页面的window对象,那么接可以使用一般操作获取元素 window.parent.document.getElementById('a').style.color="red";//dom操作 //jquery $("#a",parent.document);//$(父页面元素选择器,parent.document); $("#a",parent.document).css('border','1pxsolidred');
上面的是不存在跨域的情况,但是有时候会遇到跨域情况,在这次的项目里面就是出于跨域状态下,开始看了一些资料,说是在用一个iframe做中间层去做,但是太麻烦,在这里介绍一个十分还用的方法postMessage
postMessage
window.postMessage()方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机(两个页面的模数Document.domain设置为相同的值)时,这两个脚本才能相互通信。window.postMessage()方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
以上摘自MDN原文postMessage;
otherWindow.postMessage(message,targetOrigin,[transfer]); //otherWindow窗口对象 //message传递的消息,可以是对象,可以是字符串 //target目标窗口,*代表所有;
postMessage十分强大,既可以子传父,也可以父穿子,并且可以突破同源限制
来看我遇到的使用场景;
我在主页面有个透明遮罩,里面是一个iframe的登录窗口,在子页面点击关闭的时候,需要关掉父页面的这个登陆遮罩;在这里存在跨域,所以使用上面的获取元素,操作元素的方法不能够使用,这里使用postMassage来做
//子页面登录窗口