如何实现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的键盘控制事件说明
Apr 15 Javascript
初窥JQuery-Jquery简介 入门了解篇
Nov 25 Javascript
jquery mobile界面数据刷新的实现方法
May 28 Javascript
JS+html5制作简单音乐播放器
Sep 13 Javascript
js+html5实现侧滑页面效果
Jul 15 Javascript
浅谈React前后端同构防止重复渲染
Jan 05 Javascript
解决webpack无法通过IP地址访问localhost的问题
Feb 22 Javascript
Angular HMR(热模块替换)功能实现方法
Apr 04 Javascript
详解开发react应用最好用的脚手架 create-react-app
Apr 24 Javascript
详解在HTTPS 项目中使用百度地图 API
Apr 26 Javascript
vue项目中运用webpack动态配置打包多种环境域名的方法
Jun 24 Javascript
浅谈 JavaScript 沙箱Sandbox
Nov 02 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
MySQL数据库转移,access,sql server 转 MySQL 的图文教程
2007/09/02 PHP
PHP连接MSSQL时nvarchar字段长度被截断为255的解决方法
2014/12/25 PHP
php5.4以上版本GBK编码下htmlspecialchars输出为空问题解决方法汇总
2015/04/03 PHP
PHP的Yii框架中YiiBase入口类的扩展写法示例
2016/03/17 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
javascript模块化是什么及其优缺点介绍
2013/09/02 Javascript
jQuery实现信息提示框(带有圆角框与动画)效果
2015/08/07 Javascript
javascript+HTML5自定义元素播放焦点图动画
2016/02/21 Javascript
JS检测移动端横竖屏的代码
2016/05/30 Javascript
js+div+css下拉导航菜单完整代码分享
2016/12/28 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
教你快速搭建Node.Js服务器的方法教程
2017/03/30 Javascript
jQuery插件artDialog.js使用与关闭方法示例
2017/10/09 jQuery
浅谈vue中使用图片懒加载vue-lazyload插件详细指南
2017/10/23 Javascript
深入浅出理解JavaScript高级定时器原理与用法
2018/08/02 Javascript
vuejs选中当前样式active的实例
2018/08/22 Javascript
微信小程序的授权实现过程解析
2019/08/02 Javascript
使用 Vue 实现一个虚拟列表的方法
2019/08/20 Javascript
jQuery实现每日秒杀商品倒计时功能
2019/09/06 jQuery
微信小程序中的video视频实现 自定义播放按钮、封面图、视频封面上文案
2020/01/02 Javascript
python实现数据库跨服务器迁移
2018/04/12 Python
python re模块的高级用法详解
2018/06/06 Python
Python paramiko 模块浅谈与SSH主要功能模拟解析
2020/02/29 Python
pycharm部署、配置anaconda环境的教程
2020/03/24 Python
解决IDEA 的 plugins 搜不到任何的插件问题
2020/05/04 Python
如何使用python记录室友的抖音在线时间
2020/06/29 Python
Python基于callable函数检测对象是否可被调用
2020/10/16 Python
Etam德国:内衣精品店
2019/08/25 全球购物
屈臣氏越南官网:Watsons越南
2021/01/14 全球购物
深圳-东方伟业笔试部分
2015/02/11 面试题
什么是动态端口(Dynamic Ports)?动态端口的范围是多少?
2014/12/12 面试题
集团公司党的群众路线教育实践活动工作总结
2014/03/03 职场文书
精彩的广告词
2014/03/19 职场文书
求职自我推荐信
2014/06/25 职场文书
幼儿园保教工作总结2015
2015/10/15 职场文书
家长必看:义务教育,不得以面试 评测等名义选拔学生
2019/07/09 职场文书