window.postMessage学习(问答式)

demo在文章末尾。

window.postMessage 


1、有什么用?

答:可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面同源时,这两个脚本才能相互通信。
window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。 

2、两个页面如何算同源?

答:在JavaScript中,同源(Same-Origin)是指两个页面的协议、域名和端口都相同。这是浏览器安全策略的一部分,用于限制不同源之间的交互,以防止潜在的安全风险。同源策略(Same-Origin Policy)是浏览器的一种安全机制,它要求浏览器只允许脚本访问与其自身源相同的资源。这意味着,如果一个JavaScript脚本在一个域名下运行,那么它只能访问该域名下的资源,不能访问其他域名下的资源,除非这两个域名之间有明确的跨域资源共享(CORS)设置。

具体来说,两个页面同源需要满足以下条件:

协议相同:例如,两个页面都使用http://或https://。
域名相同:例如,两个页面都是example.com或子域名如sub.example.com。
端口相同:如果两个页面使用不同的端口号,则它们不是同源的。默认情况下,http://的端口是80,https://的端口是443,但如果明确指定了其他端口号,则必须相同。
如果两个页面不满足上述条件中的任何一个,它们就被认为是不同源的,浏览器会阻止它们之间的一些交互行为,例如:

使用XMLHttpRequest或fetch发送跨域请求。在一个窗口中通过document.domain属性来访问另一个窗口的文档对象模型(DOM)。使用window.open、window.parent、window.top等窗口对象属性来访问或操作不同源的窗口。但是,为了支持一些合理的跨域交互需求,浏览器提供了跨域资源共享(CORS)等机制,允许服务器明确指定哪些源可以访问其资源。此外,postMessage方法是一个例外,它允许不同源的窗口之间安全地传递消息,只要正确地设置消息的来源和目标。

3、targetWindow.postMessage(message, targetOrigin, [transfer]); 语法说明:

(1)targetWindow指的是什么?
在JavaScript中,targetWindow 是一个对另一个浏览器窗口或者iframe的引用。当你想要从一个窗口向另一个窗口发送消息时,你需要有对这个目标窗口的引用。
有几种方式可以获取这样的引用: 


(1.1)iframe的contentWindow属性:如果你有一个<iframe>元素在你的页面上,你可以通过它的contentWindow属性获取对该iframe内部文档的引用。例如:

<iframe id="myIframe" src="http://example.com/iframe-content.html"></iframe>
<script>var iframe = document.getElementById('myIframe');var targetWindow = iframe.contentWindow;// 现在你可以使用targetWindow来向iframe发送消息targetWindow.postMessage('Hello from parent!', '*');
</script>


(1.2)window.open返回的窗口对象:当你使用window.open方法打开一个新的窗口或标签页时,这个方法会返回一个对新打开窗口的引用。你可以使用这个引用来与新窗口通信。例如:

var targetWindow = window.open('http://example.com/new-page.html', '_blank');
// 使用targetWindow向新窗口发送消息
targetWindow.postMessage('Welcome to the new page!', 'http://example.com');


(1.3)window.frames数组或命名窗口:如果你的页面包含多个iframe或frames,你可以通过window.frames数组来访问它们。每个元素都是对应iframe或frame的窗口对象。此外,如果iframe或frame有name属性,你还可以通过window.frames['name']来访问它。例如:

<iframe name="myFrame" src="http://example.com/frame-content.html"></iframe>
<script>var targetWindow = window.frames['myFrame'];// 或者使用数组索引,如果iframe是第一个的话// var targetWindow = window.frames[0];// 使用targetWindow向iframe发送消息targetWindow.postMessage('Message from main page!', '*');
</script>


(2)message,将要发送到目标 window 的数据。字符串,对象等都可以。
(3)targetOrigin
通过窗口的 origin 属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个 URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用 postMessage 传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的 origin 属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的 targetOrigin,而不是 *。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
(4)[transfer]      (常规场景下用不到该属性)
[transfer]是一个可选参数,它是一个包含可传输对象(transferable objects)的数组。这个参数允许你在发送消息时,将某些特定类型的对象的所有权从发送方直接转移给接收方,而不是进行深拷贝。可传输对象通常指的是那些包含大量数据,并且深拷贝成本较高的对象,比如ArrayBuffer、Map、Set、TypedArray(如Int8Array、Uint8Array等)以及某些特定类型的ImageBitmap。
通过将这些对象的所有权直接转移给接收方,可以大大提高数据传输的效率,减少内存使用,并提升性能。当你传递一个对象到[transfer]数组时,该对象的所有权将被转移,发送方将不再拥有该对象,而接收方将获得对该对象的完全所有权。这意味着发送方在传输之后不能再访问或修改该对象,而接收方可以自由地使用和修改它。
下面是一个使用[transfer]参数的例子:

// 假设我们有一个名为otherWindow的引用,它指向另一个窗口或iframe
var otherWindow = window.open('http://example.com/other-page.html', '_blank');// 创建一个ArrayBuffer对象,它包含一些数据
var arrayBuffer = new ArrayBuffer(16);
var int32View = new Int32Array(arrayBuffer);
for (var i = 0; i < int32View.length; i++) {int32View[i] = i;
}// 使用postMessage发送ArrayBuffer,并将所有权转移给接收方
otherWindow.postMessage({ data: arrayBuffer }, 'http://example.com', [arrayBuffer]);// 在发送之后,发送方不能再访问arrayBuffer,因为它的所有权已经被转移了
// 尝试访问可能会导致错误
// console.log(int32View[0]); // Uncaught TypeError: Failed to read the '0' property from 'Int32Array': The object is no longer valid.// 在接收方窗口中,可以通过监听message事件来接收消息和转移的对象
otherWindow.addEventListener('message', function(event) {if (event.origin !== 'http://your-origin.com') {return; // 忽略不是来自可信源的消息}// 接收方现在拥有arrayBuffer的所有权,并可以自由地访问和修改它var receivedArrayBuffer = event.data.data;var receivedInt32View = new Int32Array(receivedArrayBuffer);console.log(receivedInt32View[0]); // 输出:0// 接收方可以修改ArrayBuffer,但这不会影响发送方,因为所有权已经转移了receivedInt32View[0] = 42;
});

在上面的例子中,arrayBuffer的所有权被转移给了otherWindow。在发送方窗口中,一旦postMessage调用完成,arrayBuffer和任何基于它的视图(如int32View)都将变得不可用,尝试访问它们会导致错误。而在接收方窗口中,event.data.data将是一个新的ArrayBuffer对象,其内容是发送方arrayBuffer的副本,并且接收方可以自由地修改和使用它。
请注意,不是所有类型的对象都可以被传输。只有那些实现了[[Transfer]]内部方法的对象才能被传输,这通常限于上面提到的那些特定类型的对象。
尝试传输不支持的对象将导致错误。

4、targetWindow能不指定吗?

答:如果不指定接收消息的窗口,那么消息只能发往本窗口,只有本窗口才会接收到信息。

5、iframe和window都是窗口吗?

答:window对象表示浏览器窗口,是JavaScript中最顶层的对象。iframe元素是HTML中的内联框架元素,可以在当前窗口中嵌套另一个窗口,因此iframe也可以被视为一个窗口。在JavaScript中,可以通过window对象来访问和操作当前窗口,而iframe元素也有自己的window对象,可以通过iframe的contentWindow属性来访问和操作iframe窗口。 

6、监听分发的 message 事件

window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {var origin = event.origin;// 验证了所受到信息的 origin (任何时候你都应该这样做)if (origin !== "http://example.org:8080") return;console.log('来信内容如下:', event.data)// 把 event.source作为回信的对象,再把 event.origin 作为 targetOriginevent.source.postMessage("谢谢,我收到你的来信了",event.origin,);
}

event的属性有
data:
从其他window传递过来的message数据
origin:
调用 postMessage 时消息发送方窗口的 origin . 这个字符串由 协议、“://“、域名、“ : 端口号”拼接而成。
例如“https://example.org (隐含端口 443)”、“http://example.net (隐含端口 80)”、“http://example.com:8080”。
source:
对发送消息的窗口对象的引用; 你可以使用此来在具有不同 origin 的两个窗口之间建立双向通信。

主页面和iframe子页面使用postMessage通讯示例:

(注意:不要用vscode自带的live preview插件打开页面,live preview打开时发现不知从哪触发的各种postMessage信息,推荐用live server插件打开页面)

index.html

<!DOCTYPE html>
<html><head><title>Main Page</title>
</head><body><h1>Welcome to the Main Page!</h1><iframe src="iframe.html" id="myIframe" width="400" height="200"></iframe><script>// 获取iframe的引用var iframe = document.getElementById('myIframe')// 监听来自iframe的消息window.addEventListener('message', function (event) {// console.log(event)// 这里仅作示例,实际应用中务必对event.origin进行验证// if (event.origin !== 'http://example.com') {//   // 验证消息的来源//   return// }alert('Received message from iframe: ' + event.data)// 回复iframeiframe.contentWindow.postMessage('Hello from Parent!', '*')}, false)// 发送消息给iframefunction sendMessageToIframe () {iframe.contentWindow.postMessage('Hello from Parent!', '*')}</script><button onclick="sendMessageToIframe()">发送消息给iframe</button>
</body></html>

iframe.html

<!DOCTYPE html>
<html><head><title>Iframe Page</title>
</head><body><h1>Welcome to the Iframe Page!</h1><button onclick="sendMessageToParent()">发送消息给parent</button><script>function sendMessageToParent () {// 向父页面发送消息parent.postMessage('Hello from Iframe!', '*')}// 监听来自父页面的消息window.addEventListener('message', function (event) {// console.log(event)// 这里仅作示例,实际应用中务必对event.origin进行验证// if (event.origin !== 'http://example.com') {//   // 验证消息的来源//   return// }alert('Received message from parent: ' + event.data)}, false);</script>
</body></html>

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

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

相关文章

初识Python语言-课堂练习【pyhton123题库】

初识Python语言-课堂练习【pyhton123题库】 一、单项选择题 1、Guido van Rossum正式对外发布Python版本的年份是&#xff1a; A 2008B 1998C 1991D 2002 【答案】C 【解析】暂无解析2、下面不是Python语言特点的是&#xff1a;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪…

移动端App、小程序、公众号该怎么选择,你真得知道吗?

当下移动App,小程序泛滥&#xff0c;如何选择&#xff0c;你真的知道吗&#xff1f; 今天我们就聊聊App、小程序、公众号、微应用具体是什么&#xff1f;怎么样开发&#xff1f;适合在什么情况下使用&#xff1f; 1.App、小程序、公众号、微应用之初识 App App本质来说就是手…

机试:蛇形矩阵

问题描述: 代码示例: //蛇形矩阵 #include <bits/stdc.h> using namespace std;int main(){int n;cout << "输入样例" << endl; cin >> n;int k 1; for(int i 0; i < n; i){if( i %2 0){//单数行for(int j 0; j < n; j){ cout &…

native关键字的理解

native关键字的理解 使用native关键字说明这个方法是原生函数&#xff0c;也就是这个方法是用C/C等非Java语言实现的&#xff0c;并且被编译成了DLL&#xff0c;由Java去调用。 本地方法是有方法体的&#xff0c;用c语言编写。由于本地方法的方法体源码没有对我们开源&#xf…

7. Linux进程环境

进程是操作系统运行程序的一个实例,也是操作系统分配资源的单位。在Linux环境中,每个进程都有独立的进程空间,以便对不同的进程进行隔离,使之不会互相影响。深入理解Linux下的进程环境, 可以帮助我们写出更健壮的代码。 在 Linux 中,进程是程序的一次执行过程,它包含了程…

日常学习2024.03.12-js中的weakSet

日常学习2024.03.12-js中的weakSet 1.WeakSet是什么&#xff1f;2.WeakSet 使用弱引用&#xff0c;Set使用强引用 1.WeakSet是什么&#xff1f; weakSet是什么呢&#xff1f;刚开始自己确实也没什么印象&#xff0c;终结学习一下吧。 WeakSet 是可被垃圾回收的值的集合&#x…

安装包逆向1

1.找到程序的入口点 在IDA中我们看到函数非常多&#xff0c;但是一般都是有主要的入口的&#xff0c;所以找一下有没有主函数 可以直接 CtrF直接查找 CNsInstaller::CNsInstaller 这里搞半天在获取文件路径 CNsInstaller::StartInstall CNsInstaller::InstallFunc char…

springboot268码头船只货柜管理系统

码头船只出行和货柜管理系统的设计与实现 摘要 针对于码头船只货柜信息管理方面的不规范&#xff0c;容错率低&#xff0c;管理人员处理数据费工费时&#xff0c;采用新开发的码头船只货柜管理系统可以从根源上规范整个数据处理流程。 码头船只货柜管理系统能够实现货柜管理…

我和我的DBA之路

这几天&#xff0c;突然想写写这些年的工作总结&#xff0c;毕业至今快20年的回顾。 想到20年前&#xff0c;在做毕业设计的时候&#xff0c;当时是学的机械工程类专业&#xff0c;因为带毕业设计的老师兼职企业有个门户网站的需求&#xff0c;而我又会用DreamWeaver做点网站设…

你的 Python 为什么需要解释一下?

Python 是一种相对简单的编程语言&#xff1b;它主要以解释型语言著称&#xff0c;这意味着每行代码都要通过解释器逐行执行。不过在某些时候&#xff0c;将 Python 代码翻译成计算机可以理解的内容&#xff0c;然后再逐行执行&#xff0c;可以减少繁琐。 在这种情况下&#x…

Spring 面试题及答案整理,最新面试题

Spring框架中的Bean生命周期是什么&#xff1f; Spring框架中的Bean生命周期包含以下关键步骤&#xff1a; 1、实例化Bean&#xff1a; 首先创建Bean的实例。 2、设置属性值&#xff1a; Spring框架通过反射机制注入属性。 3、调用BeanNameAware的setBeanName()&#xff1a…

某电信公司组织结构优化咨询项目成功案例纪实

——构建前后端组织结构&#xff0c;提升组织运营效率 随着企业的不断发展&#xff0c;行业的竞争也越来越激烈&#xff0c;企业只能不断调整自身的战略才能更好的适应这样的大环境。在战略调整的过程中&#xff0c;企业往往会面临这样的问题&#xff1a;管理层的经营理念各不…

哪些订单预计会亏?一张报表告诉你

各位数据的朋友&#xff0c;大家好&#xff0c;我是老周道数据&#xff0c;和你一起&#xff0c;用常人思维数据分析&#xff0c;通过数据讲故事。 销售订单一般是企业在销售活动中重要的单据&#xff0c;当我们接到一个客户的订单时&#xff0c;就需要在系统中录入一个销售订…

Java中的Map集合如何根据key值排序?

Java中的Map集合如何根据key值排序&#xff08;HashMap<String,Object>&#xff09;&#xff1f; Map集合的键&#xff08;key&#xff09;默认是按照它们的hashCode排序的&#xff0c;这在有时间不符合业务排序。如果你想要根据Map的key值进行排序&#xff0c;一般以下…

python自动爬取,保存并运行程序。

本文使用创作助手。 第一步&#xff08;可跳过&#xff0c;熟悉一下而已&#xff09;&#xff1a; 要在Python中新建一个文本文档并写入内容&#xff0c;可以使用文件操作功能。以下是一个示例代码&#xff1a; # 新建文本文档并写入内容 with open(output.txt, w, encoding…

STM32 | STM32F407ZE中断、按键、灯(续第三天)

上节回顾 STM32 | 库函数与寄存器开发区别及LED等和按键源码(第三天)一、 中断 中断概念 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行(面试题)。 STM32外部中断…

2024年3月11日-3月17日(全面进行)

根据月计划&#xff0c;为了要考虑把产品代码吃透。先对于计算几何&#xff0c;图像处理&#xff0c;测量学基础&#xff0c;slam进行 当然&#xff0c;也要把ue继续进行着。ue的rpg和底层渲染。收集下虚幻商城的免费资源&#xff0c;万一以后做独立游戏用得到。其他的可以暂时…

智慧城市大模型来啦!港大百度推出UrbanGPT

论文作者解读链接&#xff1a;https://blog.csdn.net/qq_42715656/article/details/136681839 项目链接&#xff1a;https://urban-gpt.github.io/ 代码链接&#xff1a;https://github.com/HKUDS/UrbanGPT 论文链接&#xff1a;https://arxiv.org/abs/2403.00813 研究实验室链…

编曲制作软件Fruity Loops Studio 21 中文版及新如何选择适合FL Studio 版本

如果你有着满腔的音乐才华&#xff0c;想要自己在家里发片吗&#xff1f;还是听 MOBY 的电子舞曲不过瘾&#xff0c;要再帮他做做 REMIX&#xff1f;有朋友会说&#xff0c;我不懂乐理&#xff0c;不懂五线谱&#xff0c;怎么制作音乐&#xff1f;这话说得很好&#xff0c;说到…

力扣-[700. 二叉搜索树中的搜索]

递归法 确定递归函数的参数和返回值 递归函数的参数传入的就是根节点和要搜索的数值&#xff0c;返回的就是以这个搜索数值所在的节点。 代码如下&#xff1a; public TreeNode searchBST(TreeNode root, int val) 确定终止条件 如果root为空&#xff0c;返回null&#xff0c…