时间:2021-03-01 编辑:
js在浏览器的两个页面之间通信详解
两个浏览器窗口间通信总结:
一个窗口更新localStorage,
另一个窗口监听window对象的”storage”事件,来实现通信。
1 2 3 4 5 6 7 8 | // 本窗口的设值代码 localStorage.setItem('aaa', (Math.random()*10).toString()) // 其他窗口监听storage事件 window.addEventListener("storage", function (e) { console.log(e) console.log(e.newValue) }) |
注:两个页面要同源(URL的协议、域名和端口相同)
每个页面开启同一个地址的WebSocket服务,利用send发送消息,利用onmessage获取消息的变化。
1 2 3 4 5 6 7 8 9 | var ws = new WebSocket("ws://localhost:3000/") ws.onopen = function (event) { // 或者把此方法注册到其他事件中,即可与其他服务器通信 ws.send({now : Date.now()}); // 通过服务器中转消息 }; ws.onmessage = function (event) { // 消费消息 console.log(event.data); } |
优点:
不仅能在不同窗口之间,还能跨浏览器,兼容性最佳。
缺点:
需要消耗点服务器资源
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事件
1 2 3 4 5 6 7 8 9 10 | //发送消息页面 < 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); |
在页面A设置一个使用 setInterval 定时器不断刷新,检查 Cookies 的值是否发生变化,如果变化就进行刷新的操作。
缺点:相当浪费资源
HTML5 中的 Web Worker 可以分为两种不同线程类型,
一个是专用线程 Dedicated Worker,
一个是共享线程 Shared Worker。
Dedicated Worker直接使用new Worker()即可创建,这种webworker是当前页面专有的。
SharedWorker可以被多个window、标签页、iframe共同使用,但必须保证这些标签页都是同源的
具体实列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // a.html < input id = 'number1' /> < input id = 'number2' /> < div class = 'result1' ></ div > var first = document.querySelector('#number1'); var second = document.querySelector('#number2'); var result1 = document.querySelector('.result1'); if (!!window.SharedWorker) { var myWorker = new SharedWorker("b.js"); first.onchange = function() { myWorker.port.postMessage([first.value, second.value]); console.log('Message posted to worker'); } second.onchange = function() { myWorker.port.postMessage([first.value, second.value]); console.log('Message posted to worker'); } myWorker.port.onmessage = function(e) { result1.textContent = e.data; console.log('Message received from worker'); console.log(e.lastEventId); } } // b.js onconnect = function(e) { var port = e.ports[0]; port.onmessage = function(e) { var workerResult = 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); } } |
其实本质上就是直接获取对方DOM
1 2 3 4 | // 父页面获取子iframe document.getElementById('iframe的id').contentWindow.document // 子iframe获取父页面 window.parent.document |
缺点
只适用于两个页面在同一域,比如在A页面中嵌套一个同源的iframe