两个浏览器窗口间通信总结:
- 1、前端轮循请求获取数据
- 2、websocket协议
- 3、localStorage ------ 同源
- 4、iframe引入另一个页面,操作另一个页面的方法— 同源
- 5、通过
window.open()
从A页面打开B页面(A、B同源),则B页面可通过window.opener
来与A页面通信 - 6、
SharedWorker
----- SharedWorker可以被多个window、标签页、iframe共同使用,但必须保证这些标签页都是同源的
1、 前端轮循获取数据 ----- setInterval【差】
在页面A设置一个使用 setInterval 定时器不断刷新,检查 Cookies 的值是否发生变化,如果变化就进行刷新的操作。
- 循环ajax请求 ,获取数据
- 消耗性能,消耗资源,不推荐;
2、WebSocket
每个页面开启同一个地址的WebSocket服务
,利用send
发送消息,利用onmessage
获取消息的变化。
var ws = new WebSocket("ws://localhost:3000/")
ws.onopen = function (event) {
// 或者把此方法注册到其他事件中,即可与其他服务器通信
ws.send({now : Date.now()}); // 通过服务器中转消息
};
ws.onmessage = function (event) {
// 消费消息
console.log(event.data);
}
优点:
- 不仅能在`不同窗口之间,
- 还能跨浏览器`,
- 兼容性最佳
- 可以前端发送信息给后台
- 服务器也会推送数据给客户端
缺点:
需要消耗点服务器资源
3、SSE (server send event) 服务器推送数据
Server-sent events:使用server-sent 事件的方法,服务器可以在任何时刻向我们的web页面推送数据和信息.这些被推送进来的信息可以在这个页面上作为事件+data来处理.
缺点:只能服务器推送数据给前端,前端无法发送数据给服务器
服务端设置
-
设置头部
"Content-type","text/event-stream"
-
返还数据格式
data:
声明数据开始
\r\n\r\n
标志数据结尾
前端获取
let source = new EventSource("/test");
source.onopen = function(){
console.log("连接建立...",this.readyState);
}
// console.log(source)
source.onmessage = function(evnet){
console.log("数据是:",evnet.data)
}
source.error = function(err){
return console.log('err');
}
4、localStorage
一个窗口更新localStorage
,
另一个窗口监听window对象的”storage”事件
,来实现通信。
// 本窗口的设值代码
localStorage.setItem('aaa', (Math.random()*10).toString())
// 其他窗口监听storage事件
window.addEventListener("storage", function (e) {
console.log(e)
console.log(e.newValue)
})
注:两个页面要同源(URL的协议、域名和端口相同)
5、SharedWorker
HTML5 中的 Web Worker 可以分为两种不同线程类型,
一个是专用线程 Dedicated Worker
,
一个是共享线程 Shared Worker
。
Dedicated Worker直接使用new Worker()即可创建,这种webworker是当前页面专有的。
SharedWorker可以被多个window、标签页、iframe共同使用,但必须保证这些标签页都是同源的
6、nodejs中使用socket.io模块实现长连接
socket.io是对websocket与异步轮询的封装,充份保证兼容
node.js服务端
const server = require('http').createServer(app.callback());
const io = require('socket.io')(server);
io.on("connection",(socket)=>{
console.log("有连接");
let obj = {
name:"张三",
age:20
}
// socket.emit("getData",JSON.stringify(obj));
socket.on("addData",function(data){
console.log(data);
// socket.emit("getData",data); // socket.eimt 一对一
socket.broadcast.emit("getData",data); // socket.broadcast 一对多
})
})
server.listen(3000);
客户端
// 安装并引入socket.io.js
npm install socket.io
//实例化
let socket = io.connect("/");
socket.on("getData",function(data){
console.log(data);
})
document.querySelector(".btn").onclick = function(){
socket.emit("addData","数据")
}
7、iframe引入另一个页面------通过iframe获取别一个页面的dom对象,进而进行进一步的操作
方法一、其实本质上就是直接获取对方DOM
// 父页面获取子iframe
document.getElementById('iframe的id').contentWindow.document
// 子iframe获取父页面
window.parent.document
缺点
只适用于两个页面在同一域,比如在A页面中嵌套一个同源的iframe
方法二、postMessage
postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递
。
消息发送:otherWindow.postMessage(message, targetOrigin);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象
、或者是命名过或数值索引的window.frames。
.message
要传递的数据,由于部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数字符串化
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,
参考链接 :https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
消息接收监听:监听message事件
//发送消息页面
<iframe onLoad="loadIFreamSite()" id="loadIframeSite" src="地址" frameborder="0" scrolling="no" allowtransparency=true style="width: 100%;" ></iframe>
function loadIFreamSite(){
var iframe = document.querySelector('#loadIframeSite');
iframe.contentWindow.postMessage({a: 1}, '*');
}
//监听消息页面
window.addEventListener('message', function(e) {
// 监听消息内容
}, true);
8、通过window.open()从A页面打开B页面(A、B同源),则B页面可通过window.opener
来与A页面通信。
当使用window.open()打开一个窗口,您可以使用window.opener
返回来自目标窗口源(父)窗口的详细信息。
window.opener.close()
将关闭源(父)窗口。
A页面
<html>
<head>
<title>父页面</title>
<meta charset="utf-8" />
</head>
<body>
<h4 onclick="openPage()">父页面</h4>
</body>
<script>
//子页面调用这个方法,与父页面通信
function say(msg){
alert(msg);
}
//通过window.open打开子页面
function openPage(){
window.open('./children.html','_blank')
}
</script>
</html>
B页面
<html>
<head>
<title>子页面</title>
<meta charset="utf-8" />
</head>
<body>
<h5 onclick="linkParentPage()">子页面</h5>
</body>
<script>
function linkParentPage(){
console.log(window.opener.document)
// 通过window.opener调用
window.opener.say('调用A页面的方法!');
}
</script>
</html>
参考链接:https://segmentfault.com/a/1190000016927268