如何实现iframe父子传参通信


Posted in Javascript onFebruary 05, 2020

在最近的项目里面,用到了不少关于iframe父子传参通信的相关操作,记录一下,虽然很简单,但是确实十分有用的;

iframe通信可以分为2种,跨域和非跨域两种.分别说明;

有一点很重要,iframe是可以给name 属性的;给上name 属性可以省下一些代码;

非跨域 父调子

//父页面
<button class="b" id="b">点击</button>
<iframe src="a.html" name='child' id="f"></iframe>

<script>
  var ob=document.getElementById('b');
  var msg='hellow,i'm your father!!'
  ob.onclick=function(){
    if(child.document.readyState=="complete"){
      child.window.fnChild(msg); //关键
    }
  }
</script>

//子页面
<script>
function fnChild (arg) {
  console.log(arg); //确实得到了 hellow,i'm your father!!
}
</script>

父页面调用子页面使用 childFrameName.window.fnName();;当然有一点很重要,你需要判断iframe 里面的东西是否加载完成,如果加载未完成就调用的话是会报错的;
判断iframe 加载是否完成有2种方法
1,childFrameName.document.readyState=="complete"来判断;
2,childFrameName.onload=function(){} 使用onload 回调函数,把调用的方法都写在这个回调函数里面;

非跨域 子调父

//在父页面
<div id="a" class="a"></div>
<iframe src="a.html" name='child' id="f"></iframe>

<script>
  function changeColor(){
    var oDiv=document.getElementById('a');
    oDiv.style.backgroundColor="red";
  }
</script>

//在子页面
<button class="ob" onclick="c()">anniu</button>
<script>
  function c(){
    parent.window.changeColor(); //关键
  }
</script>

同样的,在子页面调用父页面的方法使用 parent.window.fnName()就可以了;

这种操作难免会遇到父页面获取子页面的元素,或者子页面获取父页面的元素进行操作;

非跨域 父页面获取子页面元素操作

首先,我们有几种方法拿到子页面的window对象或者doucument 对象,(还是使用上面的html)

//原生js 获取子页面window对象
1, var childWindow=document.getElementById("f").contentWindow;
2, var childWindow=document.getElementsByTagName('f')[0].contentWindow;
//其实也就是普通的获取方法,只是后面多了一个contentWindow;
//jquery
var childWindow=$('#f').contentWindow;

//获取子页面的document对象 (假设已经通过上面的方法得到了window对象)
var frameDoc=childWindow.document;
var frameBody=frameDoc.body;
//jquery 也是跟上面的一样
var frameDoc=$(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','1px solid red');

上面的是不存在跨域的情况,但是有时候会遇到跨域情况,在这次的项目里面就是出于跨域状态下,开始看了一些资料,说是在用一个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来做

//子页面
<div id="loginBox">登录窗口</div>
<div id="close"></div>

//父页面
<div id="loginMask">
  <iframe src="子页面"></iframe>
</div>

//子页面
<script>
  let oClose=document.getElementById('#close');
  oClose.onclick=function(){
    window.parent.postMessage('close','*');
  }
</script>
//父页面
<script>
  window.addEventListener('message',function(event){
    if(event.data=='close'){
      let oLoginMask=document.getElementById('loginMask');
      oLoginMask.style.display="none";
    }
  })
</script>

上面的代码其实很简单,在子页面里面获取了元素,该元素触发点击事件的时候,向父窗口发送一个消息,传递了一个消息;(这个消息参数会在接收页面的event.data查到);
在父页面监听message事件,监听到了就让登录遮罩消失;

父传子

同样,在父窗口也可以使用postMassage 来传递消息到子页面;

//父页面
<button id="btn">传递消息</button>
<iframe id='f' src="子页面.html"></iframe>
//子页面
<div id="a"></div>

//父页面
<script>
  let oBtn=document.getElementById('btn');
  let oFrame=document.getElementById('f');
  oBtn.onclick=function(){
    oFrame.contentWindow.postMessage('hello','*');
  }
</script>

//子页面
<script>
  window.addEventListener('message',function(){
    if(event.data=='hello'){
      document.getElementById('#a').innerText=event.data;
    }
  })
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
详解JavaScript中shift()方法的使用
Jun 09 Javascript
SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
Dec 10 Javascript
基于BootStrap Metronic开发框架经验小结【九】实现Web页面内容的打印预览和保存操作
May 12 Javascript
利用Javascript实现BMI计算器
Aug 16 Javascript
在JavaScript中调用Java类和接口的方法
Sep 07 Javascript
Angular.JS实现无限级的联动菜单(使用demo)
Feb 08 Javascript
Angular中的interceptors拦截器
Jun 25 Javascript
关于javascript sort()排序你可能忽略的一点理解
Jul 18 Javascript
js实现QQ面板拖拽效果(慕课网DOM事件探秘)(全)
Sep 19 Javascript
JavaScript中Object值合并方法详解
Dec 22 Javascript
使用 Vue 绑定单个或多个 Class 名的实例代码
Jan 08 Javascript
如何实现echarts markline标签名显示自己想要的
Jul 20 Javascript
JavaScript对象原型链原理详解
Feb 05 #Javascript
基于Vue的侧边目录组件的实现
Feb 05 #Javascript
Js视频播放器插件Video.js使用方法详解
Feb 04 #Javascript
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
Feb 04 #jQuery
JS代码优化的8点建议
Feb 04 #Javascript
9种方法优化jQuery代码详解
Feb 04 #jQuery
JS代码检查工具ESLint介绍与使用方法
Feb 04 #Javascript
You might like
php根据身份证号码计算年龄的实例代码
2014/01/18 PHP
ECSHOP在PHP5.5及高版本上报错的解决方法
2015/08/31 PHP
解决PHP程序运行时:Fatal error: Maximum execution time of 30 seconds exceeded in的错误提示
2016/11/25 PHP
PHP的mysqli_stmt_init()函数讲解
2019/01/24 PHP
Javascript面向对象设计一 工厂模式
2011/12/20 Javascript
javascript学习笔记(十九) 节点的操作实现代码
2012/06/20 Javascript
JavaScript实现检查页面上的广告是否被AdBlock屏蔽了的方法
2014/11/03 Javascript
jQuery中element选择器用法实例
2014/12/29 Javascript
Javascript基础教程之定义和调用函数
2015/01/18 Javascript
使用javascript实现判断当前浏览器
2015/04/14 Javascript
javascript中attachEvent用法实例分析
2015/05/14 Javascript
js中跨域方法原理详解
2015/07/19 Javascript
js操作数据库实现注册和登陆的简单实例
2016/05/26 Javascript
简单实现js悬浮导航效果
2017/02/05 Javascript
vue 1.0 结合animate.css定义动画效果
2018/07/11 Javascript
vue子路由跳转实现tab选项卡
2019/07/24 Javascript
JS相册图片抖动放大展示效果的示例代码
2021/01/29 Javascript
Python切片知识解析
2016/03/06 Python
Python使用matplotlib绘制正弦和余弦曲线的方法示例
2018/01/06 Python
Python迭代器定义与简单用法分析
2018/04/30 Python
python读出当前时间精度到秒的代码
2019/07/05 Python
python 字典套字典或列表的示例
2019/12/16 Python
Python实现在线批量美颜功能过程解析
2020/06/10 Python
HTML5网页录音和上传到服务器支持PC、Android,支持IOS微信功能
2019/04/26 HTML / CSS
Nike澳大利亚官网:Nike.com (AU)
2019/06/03 全球购物
REISS美国官网:伦敦最受欢迎的时尚品牌
2019/08/16 全球购物
工商管理专业实习大学生自我鉴定
2013/09/19 职场文书
自考毕业生自我鉴定
2013/11/04 职场文书
餐厅经理岗位职责和岗位目标
2014/02/13 职场文书
教育技术学专业职业规划书
2014/03/03 职场文书
护理专业毕业生自我鉴定总结
2014/03/24 职场文书
食品工程专业求职信
2014/06/15 职场文书
学校安全生产月活动总结
2014/07/05 职场文书
教育系统干部作风整顿心得体会
2014/09/09 职场文书
vue3中的组件间通信
2021/03/31 Vue.js
一篇文章弄懂Python关键字、标识符和变量
2021/07/15 Python