内容简介:首先还原下业务场景,具体场景:QQ音乐页面与QQ音乐播放器,当QQ音乐页面添加歌曲时,QQ音乐播放器会自动将所操作的音乐添加至播放列表。上述业务场景就是,浏览器中的多个选项卡或窗口之间进行通信(在同一个域上,而不是CORS)的具体应用。
首先还原下业务场景, main page 主页面的某些操作会使得游览器打开新的 other page 标签页,之后当 main page 发生其他操作时候, other page 也要发生变动。
具体场景:QQ音乐页面与QQ音乐播放器,当QQ音乐页面添加歌曲时,QQ音乐播放器会自动将所操作的音乐添加至播放列表。
上述业务场景就是,浏览器中的多个选项卡或窗口之间进行通信(在同一个域上,而不是CORS)的具体应用。
其本质上都是利用一个中间介质进行数据传输,而不同介质则会导致其适用场景的不尽相同,常用的有如下几个解决方案:
window postMessage cookies localStorage
window 对象
利用 Window 接口的 open() 方法,是用指定的名称将指定的资源加载到浏览器上下文(窗口 window ,内嵌框架 iframe 或者标签 tab ),同时该方法会返回一个打开的新窗口对象的引用。
// strUrl => 新窗口需要载入的url地址,strWindowName => 新窗口的名称 // strWindowFeatures => 是一个字符串值,这个值列出了将要打开的窗口的一些特性(窗口功能和 工具 栏) let windowObjectReference = window.open(strUrl, strWindowName, [strWindowFeatures]); // windowObjectReference 为打开的新窗口对象的引用 复制代码
如果父子窗口满足“同源策略”,你可以通过这个引用访问新窗口的属性或方法。
也就是说,只用 当两个 URL 具有相同的协议,域和端口 时,才能利用 windowObjectReference 访问到页面的相关属性。
基于 windowObjectReference ,通常有两种解决跨标签页通讯的方法:
-
window.name结合setInterval:父页面利用
windowObjectReference修改name属性,子页面轮询// 父页面 let windowObjectReference = null document.getElementById('btn').onclick = function() { if (!windowObjectReference) { windowObjectReference = window.open('./other.html', 'Yang') } else { windowObjectReference.name = windowObj.name + 'NB' } } // 子页面 setInterval(function() { document.title = window.name }, 1000) 复制代码这种方法优点是向下兼容性好,缺点是利用
setInterval开销较大、且window.name只能使用字符串; -
window.location.hash结合window.addEventListener("hashchange", function, false)父页面利用
windowObjectReference动态修改location.hash,子页面利用window.addEventListener("hashchange", function, false)监听 URL 的片段标识符更改。// 父页面 let windowObjectReference = null document.getElementById('btn').onclick = function() { if (!windowObjectReference) { windowObjectReference = window.open('./other.html', 'Yang') // 有坑 windowObjectReference.onload = function() { windowObjectReference.location.hash = 'Yang' } } else { windowObjectReference.location.hash = windowObjectReference.location.hash + 'NB' windowObjectReference.focus() } } // 子页面 window.addEventListener("hashchange", function(e) { document.title = window.location.hash }, false); 复制代码这种方法开销较小,且 URL 长度受限制。
坑一:
可以从代码中可以看出,首次修改 windowObjectReference.location.hash 时,利用了 onload 事件
windowObjectReference.onload = function() {
windowObjectReference.location.hash = 'Yang'
}
复制代码
这是因为调用 window.open() 方法以后,远程 URL 不会被立即载入,载入过程是异步的。(实际加载这个URL的时间推迟到当前脚本块执行结束之后。窗口的创建和相关资源的加载异步地进行。);
坑二:
如果父页面刷新之后,重新 window.open 时,需要主要 一定要设定 strWindowName ,防止重复打开;
坑三:
需求设定子页面不能刷新,如果父页面发生刷新, windowObjectReference 为 null ,该如何通信
解决方案是利用子页面的 window.opener ,该属性能够返回打开当前窗口的那个窗口的引用,也就是父页面。
具体做法是在
// 子页面
setInterval(function() {
window.opener.windowObjectReference = window
}, 200)
复制代码
坑四:
需求又说了点击后希望自动跳转到子页面,调用 windowObjectReference.focus() 。
坑五:
坑三的赋值需要在 beforeunload 事件中 window.opener.windowObjectReference = null
postMessage API
这个解决方案最大的优点是可以安全地实现跨源通信,提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
// otherWindow 其他窗口的一个引用,如上述 windowObjectReference otherWindow.postMessage(message, targetOrigin, [transfer]); // message 将要发送到其他 window的数据 // targetOrigin 通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI 复制代码
利用上述API,我们可以完成通信工作
// 父页面
let windowObjectReference = null
document.getElementById('btn').onclick = function() {
if (!windowObjectReference) {
windowObjectReference = window.open('./other.html', 'Yang')
windowObjectReference.onload = function() {
// windowObjectReference.location.hash = 'Yang'
windowObjectReference.postMessage('Yang', windowObjectReference.origin)
}
} else {
// windowObjectReference.location.hash = windowObjectReference.location.hash + 'NB'
windowObjectReference.postMessage('NB', windowObjectReference.origin)
windowObjectReference.focus()
}
}
// 子页面
window.addEventListener("message", function (e) {
document.title = e.data
// event.source.postMessage('string', event.origin)
}, false);
复制代码
同时还可以利用 event.source.postMessage('string', event.origin) 完成双向通信(同域)。
PS:需要特别注意一点,应用该方法时, 一定要对 event.origin 进行过滤 ,具体可以参考MDN。
cookies
cookies 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
用它来完成跨标签页通信,其实和 window.name 的应用方法差不多,在实际场景中 cookies 中保存着 session 、token 等登陆信息,一般不建议用来通信,可以用来父页面和子页面共享登陆信息。
localStorage
localStorage 需要结合 window.onstorage 就是,父页面修改 localStorage ,子页面能够监听到它的变化。
// 父页面
let windowObjectReference = null
document.getElementById('btn').onclick = function() {
if (!windowObjectReference) {
windowObjectReference = window.open('./other.html', 'Yang')
windowObjectReference.onload = function() {
localStorage.setItem('hero', 'Yang')
}
} else {
localStorage.setItem('hero', 'NB')
windowObjectReference.focus()
}
}
// 子页面
window.onstorage = function (e) {
document.title = e.newValue
}
复制代码
还可以结合 JSON.stringify 传递对象等数据结构,由于利用了 window.onstorage 导致该方法的兼容性不是很好,同时 localStorage 是相同域名和端口的不同页面间可以共享。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 数据与广告(十五):商业兴趣标签建模 & XGboost 调优实战
- 数据与广告系列十五:商业兴趣标签建模&XGboost调优实战
- 广告行业中那些趣事(五):BERT 实战多标签标注模型((附 GitHub 源码)
- 【Cocos2d-x】开发实战-Cocos中的字符串、标签和中文乱码
- HTML5常用标签(2-4)链接标签及多媒体标签
- 基于标签特定文本表示的文本多标签分类
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java并发编程的艺术
方腾飞、魏鹏、程晓明 / 机械工业出版社 / 2015-7-1 / 59.00元
并发编程领域的扛鼎之作,作者是阿里和1号店的资深Java技术专家,对并发编程有非常深入的研究,《Java并发编程的艺术》是他们多年一线开发经验的结晶。本书的部分内容在出版早期发表在Java并发编程网和InfoQ等技术社区,得到了非常高的评价。它选取了Java并发编程中最核心的技术进行讲解,从JDK源码、JVM、CPU等多角度全面剖析和讲解了Java并发编程的框架、工具、原理和方法,对Java并发编......一起来看看 《Java并发编程的艺术》 这本书的介绍吧!