阅读本文
1.如何在Iframe页面间进行通信
2.了解Window.postMessage API
3.完成一个Iframe通信小demo
开源Iframe通信框架
这是我将公司内源的Iframe通信框架开源了,方便大家使用仓库地址:github.com/HaiyaoTec/w…如果对你有帮助 请给个小star鼓励一下
为什么要进行Iframe通信❓如何进行Iframe通信?Window.postMessage 详解
*window.postMessage()* 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。*window.postMessage()* 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
从广义上讲,一个窗口可以获得对另一个窗口的引用(比如 targetWindow = window.opener),然后在窗口上调用 targetWindow.postMessage() 方法分发一个 MessageEvent 消息。接收消息的窗口可以根据需要自由处理此事件 (en-US)。传递给 window.postMessage() 的参数(比如 message )将。
语法
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message
将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。[1]
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
transfer 可选
是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
白话概括一下:
Demo
先来解释一下:
/*
* A窗口的域名是,以下是A窗口的script标签下的代码:
*/
var popup = window.open(...popup details...);
// 如果弹出框没有被阻止且加载完成
// 这行语句没有发送信息出去,即使假设当前页面没有改变location(因为targetOrigin设置不对)
popup.postMessage("The user is 'bob' and the password is 'secret'",
"https://secure.example.net");
// 假设当前页面没有改变location,这条语句会成功添加message到发送队列中去(targetOrigin设置对了)
popup.postMessage("hello there!", "http://example.org");
function receiveMessage(event)
{
// 我们能相信信息的发送者吗? (也许这个发送者和我们最初打开的不是同一个页面).
if (event.origin !== "http://example.org")
return;
// event.source 是我们通过window.open打开的弹出页面 popup
// event.data 是 popup发送给当前页面的消息 "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
/*
* 弹出页 popup 域名是,以下是script标签中的代码:
*/
//当A页面postMessage被调用后,这个function被addEventListener调用
function receiveMessage(event)
{
// 我们能信任信息来源吗?
if (event.origin !== "http://example.com:8080")
return;
// event.source 就当前弹出页的来源页面
// event.data 是 "hello there!"
// 假设你已经验证了所受到信息的origin (任何时候你都应该这样做), 一个很方便的方式就是把event.source
// 作为回信的对象,并且把event.origin作为targetOrigin
event.source.postMessage("hi there yourself! the secret response " +
"is: rheeeeet!",
event.origin);
}
window.addEventListener("message", receiveMessage, false);
如果不检查origin和source容易导致跨站脚本攻击
任何窗口可以在任何其他窗口访问此方法,在任何时间,无论文档在窗口中的位置,向其发送消息。 因此,用于接收消息的任何事件监听器必须首先使用origin和source属性来检查消息的发送者的身份。 这不能低估:无法检查origin和source属性会导致跨站点脚本攻击。
与任何异步调度的脚本(超时,用户生成的事件)一样,postMessage的调用者不可能检测到侦听由postMessage发送的事件的事件处理程序何时抛出异常。
分派事件的origin属性的值不受调用窗口中document.domain的当前值的影响。
仅对于IDN主机名,origin属性的值不是始终为Unicode或punycode; 在使用此属性时,如果您期望来自IDN网站的消息,则最大程度地兼容性检查IDN和punycode值。 这个值最终将始终是IDN,但现在你应该同时处理IDN和punycode表单。
当发送窗口包含 javascript: 或 data: URL时,origin属性的值是加载URL的脚本的
参考 结束语
那么我的Iframe通信指南这篇文章就结束了,文章的目的其实很简单,就是对日常工作的总结和输出,输出一些觉得对大家有用的东西,菜不菜不重要,但是热爱,希望大家能够喜欢我的文章,我真的很用心在写,也希望通过文章认识更多志同道合的朋友,如果你也喜欢折腾,欢迎加我好友,一起沙雕,一起进步。
github:sudongyu
个人博客:速冻鱼blog
vx:sudongyuer
写在最后
伙伴们,如果喜欢我的口水话给点一个赞或者关注➕都是对我最大的支持。
前端:form表单下的 button 按钮会自动提交表单,导致 button 点击事件无效
今天在学习的时候遇到一个头疼的问题,问题的呈现就是你所看到的大大的标题,如果你也遇到了类似的问题,恭喜你,找到了解决的办法。
先看一下下述代码(不要跑,你能看懂):
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<form action="http://www.baidu.com" method="GET">
<button onclick="go()" >跳转button>
form>
<script>
function go() {
// 当点击按钮时会触发 go() 函数,进而跳转到下述界面
window.location.href = "https://blog.csdn.net/qq_43619271";
}
script>
body>
html>
分析完上述代码后,就会发现,我们理想的结果是 当点击按钮时,会跳转到 go() 函数中指定的 url,实际结果呢?看下图:
正如你所看到的,当点击按钮时跳转到了表单的提交地址,可以猜想到,当我们点击按钮时,会执行 go() 函数,但是执行完成后依然会回到原来的界面进行提交表单,所以结果就是表单提交的 URL 会覆盖掉 go() 函数中的地址。
如何处理上述的问题呢?
在菜鸟教程中我们可以看到这样的话:
button 的 type 属性:
button 的 type 属性默认是 submit ,所以当我们点击按钮的时候会自动提交表单,如果不想要让按钮自动提交表单,那么修改 type 的属性即可:
<form action="http://www.baidu.com" method="GET">
<button onclick="go()" type="button">跳转button>
form>
<script>
function go() {
// 当点击按钮时会触发 go() 函数,进而跳转到下述界面
window.location.href = "https://blog.csdn.net/qq_43619271";
}
script>
这样就不会产生覆盖的效果啦。。。。。。。。。。。。。。。