当前位置: 首页 > 科技观察

前端基础知识:如何实现两个浏览器窗口之间的通信?主要有哪些方式?

时间:2023-03-17 11:55:14 科技观察

1。localStorage一个窗口更新localStorage,另一个窗口监听窗口对象的“storage”事件,实现通信。注意:两个页面要有相同的来源(URL协议、域名和端口相同)//本窗口的设置代码localStorage.setItem('aaa',(Math.random()*10).toString())//其他窗口监听存储事件window.addEventListener("storage",function(e){console.log(e)console.log(e.newValue)})2.WebSocket所有WebSocket监听同一个服务器address并使用send发送Message,使用onmessage获取消息的变化,不仅可以window,还可以跨浏览器,兼容性极好,只是需要消耗一些服务器资源。varws=newWebSocket("ws://localhost:3000/")ws.onopen=function(event){//或者在其他事件中注册这个方法,与其他服务器通信ws.send({now:Date.now()});//通过服务器传递消息};ws.onmessage=function(event){//消费消息console.log(event.data);}3.PostMessage使用iframe或window.open查看APIotherWindow.postMessage(message,targetOrigin,[transfer]);otherWindow:对另一个窗口的引用,例如iframe的contentWindow属性,执行window.open返回的窗口对象,或命名或数字索引的window.frames。message:要发送给其他窗口的数据。它将被结构化克隆算法序列化。这意味着您可以安全地将数据对象无限制地传输到目标窗口,而无需自己序列化它们。targetOrigin:使用窗口的origin属性指定哪些窗口可以接收消息事件,它的值可以是一个字符串“”(代表***)或者一个URI。发送消息时,如果目标窗口的协议、主机地址或端口中的任何一个与targetOrigin提供的值不匹配,消息将不会被发送;只有当三者完全匹配时,消息才会被发送。该机制用于控制消息可以发送到哪些窗口;例如,当postMessage用于传输密码时,该参数尤为重要,其值必须与包含密码的消息的预期接收者的origin属性完全一致。防止密码被恶意第三方截获。如果您确切知道应该将消息发送到哪个窗口,请始终提供一个具有确切值的targetOrigin。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。transfer可选:与消息一起传递的Transferable对象字符串。这些对象的所有权将转移给消息的接收者,而发送者将不再保留所有权。/**窗口A的域名为,下面是窗口A的script标签下的代码:*/varpopup=window.open(...popupdetails...);//如果弹框没有被屏蔽并且加载完成//这行语句不发送信息,即使当前页面没有改变位置(因为targetOrigin设置错误)popup.postMessage("Theuseris'bob'andthepasswordis'secret'","https://secure.example.net");//假设当前页面没有改变位置,这条语句会成功添加消息到发送队列(targetOrigin设置正确)popup.postMessage("hellothere!","http://example.org");functionreceiveMessage(event){//我们可以信任消息的发送者吗?(可能发件人和我们原来打开的不是同一个页面)if(event.origin!=="http://example.org")return;//event.source是我们通过window.open打开的弹窗popup//event.data是popup向当前页面发送的消息"hithereyourself!thesecretresponseis:rheeeeeet!"}window.addEventListener("message",receiveMessage,false);/**弹出页面的弹出域名为,下面是script标签中的代码:*///调用A页面的postMessage时,这个函数由addEventListennerfunctionreceiveMessage(event)调用{//我们可以信任消息的来源吗?if(event.origin!=="http://example.com:8080")返回;//event.source是当前弹出页面的来源页面//event.data是"hellothere!"//假设你已经验证了接收信息的来源(你应该随时这样做),一个非常方便的方式就是把enent.source//作为回复的对象,把event.origin作为targetOriginevent.source.postMessage("hithereyourself!thesecretresponse"+"is:rheeeeeet!",event.origin);}window.addEventListener("message“,接收消息,假);4.cookie+setInterval[Bad]在A页面设置一个setInterval定时器,持续刷新,检查Cookies的值是否变化,变化则刷新。由于Cookies在同域内是可读的,所以在B页面审计的时候改变Cookies的值,A页面自然可以获取到。这样做确实可以达到想要的功能,但是这种方法相当浪费资源。虽然在这个性能过度的时代,浪费并不浪费,感觉不到,但这个实施方案确实不够优雅。5、SharedWorkerHTML5中的WebWorker可以分为两种不同的线程类型,一种是专用线程DedicatedWorker,一种是共享线程SharedWorker。DedicatedWorker可以直接使用newWorker()创建。这种webworker是当前页面独有的。.SharedWorker可以被多个窗口、选项卡和iframe使用,但必须确保这些选项卡的来源相同(相同的协议、主机和端口号)。该页面在同一个域中;可以传递objectdata(objectdata在使用instanceof进行类型判断时有陷阱);参考window.open;example://parentpagegetschildiframedocument.getElementById('iframe'sid').contentWindow.document//childiframe获取父页面window.parent.document7,window.name浏览器窗口有window.name属性。该属性最大的特点是,无论同源与否,只要前一个网页在同一个窗口设置了该属性,后一个网页就可以读取。父窗口首先打开一个子窗口,从不同的来源加载网页,网页将信息写入window.name属性。窗口名称=数据;然后,子窗口跳转回与主窗口具有相同域的URL。window.location.href='http://parent.url.com/xxx.html';然后,主窗口可以读取子窗口的window.name。vardata=document.getElementById('iframe'sid').contentWindow.name;这种方式的好处是window.name容量大,可以放很长的字符串;缺点是必须监听子窗口的window.name属性的变化,影响网页性能。