window.postMessage实现网页间通信
window.postMessage() 方法可以安全地实现跨域通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
一、安装live-server
要想实现跨窗口通信,必须要在服务器上运行,直接用浏览器打开HTML文件只能处理单个文件,窗口之间无法通信。
npm install -g live-server
使用命令live-server进行启动。
安装live-server,在任意位置启动服务器。
在服务器中启动之后,会看见文档中多了一个script标签。这段代码是由live-server插入的。当运行在后台的live-server检测到文件变化,就会通过websockt向网页发送“reload”消息,从而可以实现浏览器中的网页总是实时的响应文件的变更。
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
二、基础知识
MessageEvent有以下几个属性:
- data:从其他window中传递过来的对象
- origin:调用 postMessage 时消息发送方窗口的 origin
- source:对发送消息的窗口对象的引用; 您可以使用此来在具有不同origin的两个窗口之间建立双向通信。
在发送数据窗口执行:otherWindow.postMessage(msg,origin)
- otherWindow:表示接受数据的窗口的window对象,包括iframe的子窗口和通过window.open打开的新窗口。
- msg表示要发送的数据,包扩字符串和对象(ie9以下不支持,可以利用字符串和json互换)。
- origin表示接收的域名。
三、最简单的一个demo
父窗口打开一个子窗口,然后询问子窗口:“吃饭了吗”,子窗口回复父窗口:“吃了”
father.html
<html>
<body>
</body>
<script>
window.addEventListener("message", function(e) {
document.querySelector("body").appendChild(document.createTextNode('son say: ' + e.data))
})
var son = window.open("son.html")
son.onload = function() {//必须得要等到儿子加载完成才可以说话
son.postMessage("吃饭了吗", location.href)
}
</script>
</html>
son.html
<html>
<body>
</body>
<script>
window.addEventListener("message", function() {
console.log(event)
document.querySelector("body").appendChild(document.createTextNode("father say: " + event.data))
event.source.postMessage("吃了", event.origin)
})
</script>
</html>
四、一个网页聊天系统
father.html
<html>
<head>
<style>
textarea,
input {
width: 80%;
font-size: 20px;
font-family: "Consolas";
}
textarea {
height: 80%;
}
input {
height: 10%;
}
</style>
</head>
<body>
<div style="text-align:center">
<textarea readonly></textarea>
<input type="text" style="margin-top:10px" onkeydown="keydown()">
</div>
</body>
<script>
function $(sel) {
return document.querySelector(sel)
}
window.addEventListener("message", function() {
$("textarea").value += "\nson say: " + event.data
})
var son = window.open("myson.html")
function keydown() { //这里不需要传递参数,直接使用event就可以
if (event.keyCode == 13) {
son.postMessage($("input").value, location.href)
$("textarea").value += "\n我说:" + $("input").value
$("input").value = ""
event.preventDefault
}
}
</script>
</html>
myson.html
<html>
<head>
<style>
textarea,
input {
width: 80%;
font-size: 20px;
font-family: "Consolas";
}
textarea {
height: 80%;
}
input {
height: 10%;
}
</style>
</head>
<body>
<div style="text-align:center">
<textarea readonly></textarea>
<input type="text" style="margin-top:10px" onkeydown="keydown()">
</div>
</body>
<script>
var father = null
window.addEventListener("message", function() {
$("textarea").value += "\nfather say: " + event.data
if (father == null) {
father = {
source: event.source,
origin: event.origin
}
}
})
function $(sel) {
return document.querySelector(sel)
}
function keydown() { //这里不需要传递参数,直接使用event就可以
if (event.keyCode == 13) {
father.source.postMessage($("input").value, location.href)
$("textarea").value += "\n我说:" + $("input").value
$("input").value = ""
event.preventDefault
}
}
</script>
</html>
五、最后一个demo
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="button" value="Open Window" onclick="openWin()" />
</body>
<script>
window.addEventListener("message", function(evt) {
var ele = document.createElement("pre")
ele.innerText = "son say:" + JSON.stringify(evt.data)
document.querySelector("body").appendChild(ele)
})
var popupwin = window.open("son.html");
//onload只能执行一次,也就是如果子窗口有onload事件,可能会覆盖。
popupwin.onload = function(e) {
var params = "天下大势为我所控"
var origin = location.href
popupwin.postMessage(params, origin);
}
popupwin.onunload = function(e) {
var ele = document.createElement("h1")
ele.innerText = "儿子最后说:" + popupwin.returnValue
document.querySelector("body").appendChild(ele)
}
</script>
</html>
son.html
<html>
<head>
<title>popup window</title>
</head>
<body>
<button onclick="closeWin()">点我返回</button>
<div id="show"></div>
</body>
<script>
function closeWin() {
window.returnValue = "这是返回值";
window.close();
}
//HTML DOM fully loaded, and fired window.onload later.
document.onreadystatechange = function() {
if (document.readyState === 'complete') {
window.addEventListener('message', function(event) {
document.querySelector("#show").appendChild(document.createTextNode("father say:" + e.data))
event.source.postMessage("what's the fuck", event.origin)
});
}
};
</script>
</html>
六、安全问题
如果您不希望从其他网站接收message,请不要为message事件添加任何事件侦听器。
如果您确实希望从其他网站接收message,请始终使用origin和source属性验证发件人的身份。
当您使用postMessage将数据发送到其他窗口时,始终指定精确的目标origin,而不是*。
参考资料
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
window.postMessage实现网页间通信的更多相关文章
- JavaScript 跨域:window.postMessage 实现跨域通信
JavaScript 跨域方式实现方式有很多,之前,一篇文章中提到了 JSONP 形式实现跨域.本文将介绍 HTML5 新增的 api 实现跨域:window.postMessage . 1 othe ...
- 利用HTML5的window.postMessage实现跨域通信
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp77 HTML5的window.postMessage简述 postM ...
- window.postMessage跨文档通信
window.postMessage 1.浏览器兼容情况:IE8+.chrome.firefox等较新浏览器都至此. 2.使用方法: a.otherWindow.postMessage( messag ...
- 使用window.postMessage实现跨域通信
JavaScript由于同源策略的限制,跨域通信一直是棘手的问题.当然解决方案也有很多: document.domain+iframe的设置,应用于主域相同而子域不同: 利用iframe和locati ...
- 用HTML5里的window.postMessage在两个网页间传递数据
说明 window.postMessage()方法可以安全地实现Window对象之间的跨域通信.例如,在一个页面和它生成的弹出窗口之间,或者是页面和嵌入其中的iframe之间. 通常情况下,不同页面上 ...
- 跨域通信--Window.postMessage()
一.跨源通信概述 源:协议.端口号(https默认值433).主机域名(document.domain) 作用:向目标窗口派发MessageEvent消息(四个属性) 兼容参考 MessageEven ...
- window.postMessage 跨窗口,跨iframe javascript 通信
同源通信 执行它们的页面位于具有相同的协议(http/https),端口(80/443),主机(通常为域名) 时,这两个脚本才能相互通信 大多数情况下,网站就是内部的域名,所以是同源通信,可以相互访问 ...
- HTML5之worker开启JS多线程模式及window.postMessage跨域
worker概述 worker基本使用 window下的postMessage worker多线程的应用 一.worker概述 web worker实际上是开启js异步执行的一种方式.在html5之前 ...
- 系统间通信(9)——通信管理与RMI 下篇
接上文<架构设计:系统间通信(8)--通信管理与RMI 上篇>.之前说过,JDK中的RMI框架在JDK1.1.JDK1.2.JDK1.5.JDK1.6+几个版本中做了较大的调整.以下我们讨 ...
随机推荐
- 可操纵网页URL地址的js插件-url.js
url.js是一款能够很有用方便的操纵网页URL地址的js插件.通过url.js你能够设置和获取当前URL的參数,也能够对当前URL的參数进行更新.删除操作.还能够将当前URL的參数显示为json字符 ...
- OpenCV学习(19) 细化算法(7)
最后再来看一种通过形态学腐蚀和开操作得到骨架的方法.http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/ 代码非常简单: v ...
- 第十章 Redis持久化--RDB+AOF
注:本文主要参考自<Redis设计与实现> 1.Redis两种持久化方式 RDB 执行机制:快照,直接将databases中的key-value的二进制形式存储在了rdb文件中 优点:性能 ...
- [置顶] Android异步加载数据库和多线程编程
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发.尚未有统一中文名称,中国大陆地区较多人使用“安卓” ...
- Sql Server-查询一列的数据进行拼接
select convert(VARCHAR(10),memberid) +',' from t_member where teamid = 1009 for xml path('')
- linux python调试技巧
Linux下Python基础调试 http://blog.163.com/liuyuhuan0915@126/blog/static/78265448201141662828820/ 当手边没有IDE ...
- cocos2d-x3.0创建第一个jsb游戏
第一步: 最新的cocos2d-x.下载地址https://github.com/cocos2d/cocos2d-x github上最新的引擎,值得注意的是官网上发布的引擎是稳定版.选择哪种就看个人喜 ...
- 监听器(web基础学习笔记二十二)
一.监听器 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通java程序,这个程序专门 ...
- vue 开发中的常见问题
(一)eslint静态检查 在大家用vue-cli创建工程的时候,会有一项,使用使用eslint,如果选择了y,那么工程就会安装并启用eslint. 这里列举一下常见的错误: 1.多余的分号 2.定义 ...
- Hat’s Words(字典树)
Problem Description A hat's word is a word in the dictionary that is the concatenation of exactly tw ...