Iframe通信

news2025/7/16 15:21:14

 跨域的种类

一般有两种形式的跨域问题:

 ①使用XmlHttpRequest(XHR)或者使用AJAX发送的POST或者GET请求。这种形式的跨域是:前端页面与后端进行的跨域请求。

②父子页面之间进行的DOM操作(父子窗口之间的document操作)。这种形式的跨域是:前端页面与前端页面之间的通信或者相互操作的形成跨域。(本文主要讲这种)

iframe通信方式:

  • 同域直接通过iframe的contentWindow 和parent去操作相应的窗口内的window.document....
  • 主域不同,设置document.domain就可以如上操作
  • 跨域及不跨均可应用:window.name、location.hash、postMessage和onmessage

访问iframe: contentWindow
访问父级:parent
访问顶级:top

1、不跨域:

父:

<body> 
    <textarea id="message">这是高层的密码!</textarea><br/> 
    <button id="test">看看员工在说什么</button><br/><br/><br/>
    员工们:<br/> 
    <iframe src="b.htm" width="500" height="300" id="iframe"></iframe> 
    <script> document.getElementById("test").onclick = function(){ 
    alert(document.getElementById("iframe").contentWindow.document.getElementById("message").value); 
  }
    </script> 
</body> 

子:

<html xmlns="http://www.w3.org/1999/xhtml">
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>JSONP方式</title><script type="text/javascript" src="/js/jquery-1.5.1.min.js"></script> </head>
<body> 
    <textarea id="message">这是员工的密码!</textarea><br/>
    <button id="test">看看领导在说什么</button><br/> 
    <script> document.getElementById("test").onclick = function(){ alert(parent.document.getElementById("message").value); } </script>
</body>
</html>

2、主域相同、子域不同

使用document.domain=主域名

document.domain设置规则:

  •  document.domain只设置域名或者IP地址。即:没有协议(http/https),没有端口。
  • 如果访问的地址是域名形式,则document.domain只能设置为当前域名下的同级或者父级域名,并且不能设置为顶级域名,也不可以设置为其他形式的域名(不是当前域名的父级或同级)。

例如:当前访问地址为:https://mp.csdn.net/mp_blog/creation/editor/121540023(当前页面)。可以打开Chrome的控制台(F12)找到console的tab。默认情况下,我们输入document.domain会显示‘csdn.net’。其中csdn.net就是https://mp.csdn.net的父级域名。我们也可以设置为mp.csdn.net。因为mp.csdn.net是mp.csdn.net的同级域名。

但是我们不能设置顶级域名,即document.domain='net',就会提示错误信息。也不能设置其他的域名形式。即document.domain='csdn1.net'或者document.domain='baidu.com'。提示也说得很清楚。必须是mp.csdn.net的一个后缀形式。

  • 如果访问地址是IP的形式,则document.domain只能设置一样的IP地址。

 注意:根据上面的设置规则,在使用document.domain的方式时,页面之间必须有相同的父级域名。否则这种方式将无法进行操作。

a.html (http://a.xxx.com/js/crossdomain/demo/a.htm)

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>A</title>
</head>
<body>
<textarea id="message">这是高层的密码!</textarea><br/>
<button id="test">看看员工在说什么</button><br/><br/><br/>员工们:<br/>
<iframe src="http://b.xxx.com/js/crossdomain/demo/b.htm" width="500" height="300" id="iframe"></iframe>
<script>
    document.domain = "jiaju.com";

   document.getElementByI d("test").onclick = function(){
        alert(document.getElementByI d("iframe").contentWindow.document.getElementByI d("message").value);
    }
</script>
</body>
</html>

b.html ((http://b.xxx.com/com/js/crossdomain/demo/b.htm ))

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JSONP方式</title>
<script type="text/javascript" src="/js/jquery-1.5.1.min.js"></script>
</head>
<body>
<textarea id="message">这是员工的密码!</textarea><br/>
<button id="test">看看领导在说什么</button><br/>
<script>
    document.domain = "jiaju.com";
    document.getElementByI d("test").onclick = function(){
        alert(parent.document.getElementByI d("message").value);
    }
</script>
</body>
</html>

 两个域都设置:document.domain=‘jiaju.com’

3、主域不同

1)location.hash

location.hash原理:
1、动态改变location.hashiframe不会重载
2、无论跨域与否,iframe内可以获取自己的location.hash
3、只要域名相同就能通信,即使ABC三层嵌套

a.html(http://www.aaa.com/demo/cross/iframe03/a.htm)嵌套了b.html(http://www.bbb.com/demo/cross/iframe03/b.html)

//父页面通过hash像子页面传值
var iframe = document.getElementByI d("iframe")
修改iframe.src改变其hash

//子页面监听hash改变,获取hash上的值:window.location.hash


//子页面=》父页面:要知道iframeid
var hash_url = window.location.hash,
      datas = hash_url.split("#")[1].split("&"),
      data = {};

for(var i = 0;i<datas.length;i++){
    var t = datas[i].split("=");
    data[t[0]] = decodeURIComponent(t[1]);
}
document.domain = "jiaju.com";
switch(data["JJtype"])
    {
        case "height":
            try{top.window.document.getElementByI d(data["iframeID"]).height = data["height"];}catch(e){}
            break
        case "width":
            try{top.window.document.getElementByI d(data["iframeID"]).width = data["width"];}catch(e){}
            break
        case "callback":
            try{top.window[data["fn"]].call(document,data);}catch(e){}
            break
        default:
    }

location.hash缺点
1、传递数据量有限
2、不太安全

2)window.name

location.hash缺点
1、传递数据量有限
2、不太安全

window.name

window.name 是什么:
name 在浏览器环境中是一个全局window对象的属性
当在 iframe 中加载新页面时,name 的属性值依旧保持不变
name 属性仅对相同域名的 iframe 可访问
window.name 的优势:

  • 数据量更大(2M)
  • 更安全
  • 可传递多种数据格式

window.name 的劣势:

  • 只适用于隐藏iframe的情形

原理(1) :
A创建iFrame B,把要传递的数据放入window.name

打开Chrome的控制台,当前地址为:www.baidu.com。你在console的控制台中输入window.name='moxiao',然后将当前页面的地址栏的地址改为:mai.qq.com,然后在console的控制台中打印window.name将会显示:‘moxiao’

跨域iframe怎么调用父页面方法

 若父页面: parent.html;嵌在父页面的子iframe页面:child.html

1)同域时 iframe 调用父页面的JS方法

在同域的情况下,子iframe页面可以很方便地直接调用父页面定义的JS方法:window.parent.fn(); 或者 window.top.fn();

  • window.self: 当前窗口自身的引用
  • window.parent: 上一级父窗口的引用
  • window.top: 最顶层窗口的引用

当页面中不存在 iframe 嵌套时,则 window.self, window.parent, window.top 三者均是当前窗口自身的引用。

2)不同域时 iframe 调用父页面的JS方法

不同域时上面方式调用,不报跨域错误

postMessage 的发送与接收,Window.postMessage 是 HTML5 提供的一个跨域解决方案

1、发送:otherWindow.postMessage(message, targetOrigin, [transfer]);

  • otherWindow:其他窗口的一个引用,如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames; 
  • message: 将要发送到其他 window的数据;
  • targetOrigin: 通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串”*”(表示无限制)或者一个URI。

2:接收:

//event.data :传递过来的信息,也就是 postMessage 中发出的 message;
//event.origin: 发送信息页面的域名,包括协议和端口号。
window.addEventListener("message", function(event){
    var data = event.data;  
    // 判断域名
    if(event.origin == 'http://192.168.1.237'){
        //doSomething()
    }
});
  • 父页面像子页面通信:ifram的contentWindow.postMessage
  • 子页面像父页面通信:window.parent.postMessage或window.top
  • 接收的话直接window监听onmessage事件即可

实现:

  • a.com 域名下的父页面 parent.html 定义了功能函数 sayHi();父页面 parent.html 中嵌套了子 iframe 页面 child.html(在域名b.com域名下) 。
  • 在child.html中引起触发、执行父页面定义的 sayHi()方法。
  • 在child.html中向父页面请求获取数据 uname 值。

1) child.html代码:

<script type="text/javascript" src="sdk_child.js"></script>
<script type="text/javascript">
    // 1)触发父页面定义的方法
    window.SDK.sayHi({msg: 'hi'});
    
    // 2)向父页面请求获取数据 uname
    var uname = '';
    window.SDK.getUname();
    setTimeout(function(){
        uname = window.SDK.uname;
        //doSomething(uname);
    }, 200);
    // 备注:发送请求后,需要延时接收返回的数据
</script>

2) child.html 中引入的js文件 sdk_child.js 代码:

;(function(){
    var sdk = window.SDK || {};
    sdk.uname = null;

    //发送
    sdk.getUname = function(){
        window.top.postMessage({
            action: "getUname"
        }, "*")};
    sdk.sayHi = function(info){
        window.top.postMessage({
            action: "sayHi",
            info: {
                msg: info.msg
            }
        }, "*")};
    //接收
    window.addEventListener("message", function(e){
        var res = e;
        var action = res.data.action;
        var info = res.data.info;
        //判断域名
        if(res.origin == 'a.com'){
            switch (action) {
                case 'getUname' :
                    sdk.uname = info;
                    break;
                default :
                    return
            }
        }
    });
    //写入window
    window.SDK = sdk;
})();

3) parent.html 中引入的js文件 sdk_parent.js代码:

;(function(){
    var iframecont = document.getElementById('gameIframe').contentWindow;
    var sdk ={
        getUname: function(){
                var info = Tool.pareUrl(location.href);
                iframecont.postMessage({action: 'getUname', info: 'zhangsan'}, 'b.com');
            },
        sayHi: function(info){
                alert(info.msg);
        },
    };

    //监听接收
    window.addEventListener("message", function(e){
        var res = e;
        var data = e.data;
        var info = e.data.info;
        if(true){
            switch (data.action) {
                case 'sayHi' :
                    sdk.sayHi(info);
                    break;
                case 'getUname' :
                    sdk.getUname();
                    break;
                default :
                    return
            }
        }
    });
})();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/38103.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用XShell、XFTP 连接 win7 虚拟机(windows、Linux无法远程登录问题)

文章目录前言出错原因&#xff08;题外话&#xff09;那么我们为什么要使用 SSH 连接开始操作&#xff08;Windows7&#xff09;首先进行 SSH 测试获取所需的openSSH文件安装openSSH添加环境变量ssh测试发布ssh服务开始操作&#xff08;Linux&#xff0c;以Ubuntu为例&#xff…

Linux启动流程分析

一、Linux启动流程图 二、硬件启动流程 2.1、POST Linux开机加电后&#xff0c;系统开始开机自检&#xff0c;该过程主要对计算机各种硬件设备进行检测&#xff0c;如CPU、内存、主板、硬盘、CMOS芯片等。主要完成检测硬件能否满足运行的基本条件&#xff0c;叫做“硬件自检(P…

【网络编程】第一章 网络基础(协议+OSI+TCPIP+网络传输的流程+IP地址+MAC地址)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

onnx-modifier使用

文章目录**0、作用和功能****1、准备****2、界面介绍****3、注意tips**onnx-modifier基于流行的模型可视化工具 Netron 和轻量级Web应用框架 flask 开发。希望它能给社区带来一些贡献0、作用和功能 经常作为不同框架模型转化的中间文件&#xff0c;拿到ONNX文件&#xff0c;想…

KMP算法【一句话概括什么是KMP】【手写 求next数组】【手写匹配过程】

这里写自定义目录标题1. 什么是KMP算法2. next数组的表示含义怎么算3. 匹配过程例题——KMP字符串1. 什么是KMP算法 KMP算法&#xff1a;给定abcabm字符串和abcabcabm字符串&#xff0c;求前面字符串在后面字符串出现的位置&#xff0c;我们从头开始依次遍历&#xff0c;当遍历…

Supervisor - 用户进程监控利器

Supervisor Supervisor 是一个客户端/服务器系统&#xff0c;允许用户在UNIX操作系统上监视、控制用户进程。从定义里面分析包含两层意思。 监控进程 - 监控进程状态 确定当前进程是否发生异常控制进程 - 针对进程异常情况 控制进程的行为 如重启当前进程 Supervisor 通过 F…

神经网络和深度学习-logistic回归

logistic回归 logistic回归常用于分类问题 &#xff0c;根据输入的x来估计属于不同类的概率为多少&#xff0c;满足分布&#xff0c;即所有类的概率总和为1 在torchvison包中提供了一些常用的数据集&#xff0c;供我们使用&#xff0c;例如&#xff1a;Mnist数据集 Cifar-10数…

力扣算法入门刷题2

12、删除排序链表中的重复元素 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2[ //链表结构 public class ListNode {* int val;* List…

【情感识别】BP神经网络语音情感识别【含Matlab源码 349期】

⛄一、BP神经网络语音情感识别简介 0 引言 随着科技的迅速发展, 人机交互显得尤为重要。语音是语言的载体, 是人与人之间交流的重要媒介。相较于其它交流方式而言, 语音交流更加直接、便捷。近年来, 随着人机交互研究的不断深入, 语音情感识别更成为了学术界研究的热点, 其涉及…

3年测试经验,投了300多份简历,没公司要我...

前言 软件测试行业3年多经验&#xff0c;学历大专自考本科&#xff0c;主要测试方向web&#xff0c;PC端&#xff0c;wap站&#xff0c;小程序公众号都测试过&#xff0c;app也测过一些&#xff0c;C端B端都有&#xff0c;除功能外&#xff0c;接口性能也有涉猎&#xff0c;但…

一条命令能实现前端本地代码和打包仓库的自动化提交?

背景&#xff1a; 先介绍我们原本的代码上线流程&#xff1a;首先发布仓和代码仓&#xff08;dev和master分支对应测试和生产环境&#xff09;独立&#xff0c;每次修复或新增功能&#xff0c;首先需要提交改动到代码仓&#xff08;fork&#xff09;&#xff0c;然后打包代码&…

TI Sitara系列 AM64x开发板——FreeRTOS、Baremetal案例开发案例

前 言 3 1 开发环境搭建 2 CCS工程编译与加载 3 FreeRTOS与Baremetal案例 评估板简介 创龙科技TL62x-EVM是一款基于TI Sitara系列AM62x单/双/四核ARM Cortex-A53 + 单核ARM Cortex-M4F异构多核处理器设计的高性能低功耗工业评估板,由核心板和评估底板组成。处理器ARM Cor…

SpringCloud之微服务实用篇2

在之前我们学习微服务中的两个组件&#xff0c;一个是注册中心&#xff0c;一个负载均衡器。今天&#xff0c;我们主要学习三个内容&#xff0c;分别是&#xff1a;Nacos配置管理、Feign远程调用、Gateway服务网关。 目录 一、Nacos配置管理 1.1、Nacos实现配置管理 1.2、微…

Redis持久化策略AOF、RDB详解及源码分析

写在前面 以下内容是基于Redis 6.2.6 版本整理总结 一、Redis为什么要持久化 Redis 是一个内存数据库&#xff0c;就是将数据库中的内容保存在内存中&#xff0c;这与传统的MySQL&#xff0c;Oracle等关系型数据库直接将内容保存到硬盘中相比&#xff0c;内存数据库的读写效…

数论简单问题

数论基本问题约数个数问题约数之和问题1-n中所有1-n因子的数量n!分解后某个质因子的个数欧拉函数公式法求欧拉函数线性筛求欧拉函数欧拉函数在线性筛中的三种情况&#xff1a;欧拉定理逆元费马定理求逆元快速幂求逆元扩展欧几里得算法扩展欧几里得算法证明扩展欧几里得的应用中…

消息队列 - RabbitMQ

1. 名词解释 Producer&#xff1a;生产者 Broker&#xff1a;接收和分发消息的应用 Connection&#xff1a;生产者和消费者与 Broker 之间的 TCP 连接 Channel&#xff1a;信道&#xff1b;在 Connection 内部建立的逻辑连接&#xff0c;每个 Channel 之间是相互隔离的。相…

第十四届模拟赛第二期试题【Java解析】

目录 ✏️写在前面 ✨历史回顾 &#x1f388;第一题&#xff08;二进制API&#xff09; 代码&#xff1a; 思路&#xff1a; &#x1f388;第二题&#xff08;闰年问题/时间API&#xff09; 代码1&#xff1a; 思路1&#xff1a; 代码2&#xff1a; 思路2&#xff1a…

【计算机网络】数据链路层:使用点对点信道的数据链路层

数据链路层信道类型&#xff1a; &#xff08;1&#xff09;点对点信道&#xff1a;使用一对一的点对点通信方式 &#xff08;2&#xff09;广播信道&#xff1a;使用一对多的广播通信方式。 必须使用专用的共享信道协议来协调主机数据发送。 链路:从一个节点到相邻节点的一…

TCP的三次握手和四次挥手

目录:smile_cat:基础知识回顾1、运输层概述2、端口号3、复用与分用:smiley_cat:重点知识来袭1、TCP和UDP2、三次握手3、四次挥手4、TCP报文段首部格式文章参考来源&#xff1a; TCP的三次握手和挥手–飞天小牛肉20-1-tcp连接——初始化序列号(ISN)_网络安全-CSDN博客_初始序列…

掌握分布式环境缓存更新策略,提高缓存与数据库数据一致性

概述 随着时代的发展&#xff0c;服务系统架构也已经由最初的单体架构转变为分布式、微服务架构模式。 从数据体量上来看&#xff0c;各系统存储的数据量越来越大&#xff0c;数据的查询性能越来越低。 此时&#xff0c;就需要我们不断的进行优化&#xff0c;最常用的就是引入…