最近要把之前的打包下载改成后台下载,所谓后台,就是要新打开一个浏览器页签,在页签进行下载,我需要把文件信息传过去,这就涉及到了页签之间的通信,我选择了
BrodcastChannel
,其实有很多通信的方式,并不是BrodcastChannel
有多优秀,而是我一百度就搜到了吗,看到了我就直接用了,没对比过其他的,大家可以去看看别的方法。可能这也不是多难的需求,但是我之前没做过,也踩了坑,没准还可以帮助一下路过的人,所以记录一下。
我的思路是点击下载按钮,使用window.open()打开新页签,这个方法的返回值是新页签的window对象,window对象中的closed属性和focus方法比较关键,closed的值是布尔值,代表这个窗口是否已经关闭。调用focus可以聚焦到当前窗口。
js
主页面
let newWindow = null //用于存放新打开页签的window
const BC = new BrodcastChannel('BC_NAME') //new一个BC
const downLoadFile = ()=>{
//如果newWindow没有值或者newWindow.closed是true,说明新页签从来没打开过,或者已经关闭了
//这种情况就重新打开新页签
if(!newWindow || newWindow.closed){
newWindow = window.open(newWindowUrl)
newWindow.onload = ()=>{
//在新页面加载完毕时发送消息
BC.postMessage('message')
}
}else{
//newWindow.closed为true走到这里
//发送消息,聚焦过去
BC.postMessage('message')
newWindow.focus()
}
}
好像这个需求就快快乐乐的结束了,剩下的写写业务代码完事了,但是我在原页签点击了刷新,什么变量什么BC都会消失,而且window也无法存进storage,我该如何是好,我即无法判断新页签的状态,也无法使用focus聚焦。 所以聪明的我准备使用localstorage标记状态,window.open之后我就setItem,新页签销毁时我就removeItem,这样不就可以判断状态了吗。果然是我。那怎么聚焦呢,我在消息中加一个标识,用来判断是不是第一次打开,下载页面接收到消息时判断一下是不是第一次打开,如果不是,那就调用一下focus不就完了吗,就酱紫。
js
主页面
const BC = new BrodcastChannel() //new一个BC
const downLoadFile = ()=>{
//如果flag没有值,说明新页签从来没打开过
//这种情况就重新打开新页签
const flag = localStorage.getItem('flag') //取一下这个状态
const data = {msg:'message',first:flag}
const params = JSON.stringify(data)
if(!flag){
const newWindow = window.open(newWindowUrl)
newWindow.onload = ()=>{
//在新页面加载完毕时发送消息
localStorage.setItem('flag','down')
BC.postMessage(params)
}
}else{
//flag有值走到这里
//发送消息,聚焦过去
BC.postMessage(params)
}
}
js
下载页面
onMounted(()=>{
const BC = new BrodcastChannel('BC_NAME') //new一个BC,建立通道
BC.onmessage = ({data})=>{
const {msg,first} = JSON.parse(data)
......处理数据不写了
//如果有flag调用focus
first&&window.focus()
}
})
onUnmounted(()=>{
localStorage.removeItem('flag')
})
单纯的我以为这样就可以了,但是window.focus失效了,这是为什么,我急忙打车去问ChatGtp,他是这样说的。
估计是因为中了第三点的原因,不过发现这个问题的同时我也发现了另一个华点。 window.open的完全体 window基本语法
window.open(URL, windowName, windowFeatures);
我发现他可以通过名字跳转页面,只要第二个参数传递新页签的名字就好了,那我何必拘泥与focus呢,最终:
js
主页面
const BC = new BrodcastChannel() //new一个BC
const downLoadFile = ()=>{
//如果flag没有值,说明新页签从来没打开过
//这种情况就重新打开新页签
const flag = localStorage.getItem('flag') //取一下这个状态
if(!flag){
const newWindow = window.open(newWindowUrl,'myWindow') //这里可以定义新页签的名字
newWindow.onload = ()=>{
//在新页面加载完毕时发送消息
localStorage.setItem('flag','down')
BC.postMessage('message')
}
}else{
//flag有值走到这里
//发送消息,聚焦过去
BC.postMessage('message')
window.open('javascript:;','myWindow')
//至于为什么url那里写'javascript:;'我也不清楚,我是百度的,有知道的可以留言
}
}
文章中的描述和代码都是在掘金页面敲的,没有代码提示可能有错别字或者写错的地方,大家发现了给我留言哦。