共计 1727 个字符,预计需要花费 5 分钟才能阅读完成。
原文地址
这是一篇拖更了一个月的文章,200727 才想起来把它写了,让咱们坐上工夫穿梭机回到一个月前。
最近写后盾的前端遇到奇葩的需要,单体利用要做出多开多个 Tab。而且有些数据不能从独自的接口获取,它会在第一次接口申请全副返回。因为数据量太大,如果关上新 Tab 的时候再申请一次体验不大好,也存在节约申请的状况。因而一个技术需要就呈现了,须要一个在多不同 Tab 之间互相通信的机制。
第一版的实现是间接用的 localStorage,给本人挖了一个坑(真蔡)。因为刷新页面的时候还要能从新读取数据,所以不能利用 localStorage 写入、读取之后就立马革除掉。上线之后没过多久失去反馈页面关上之后空白,因为我这边关上失常,一开始没太在意。不久之后又失去同样的反馈,看来还是得排除一下问题了。间接去反馈者查看一下异样信息,看来是 localStorage 超过了空间限度。先给了他们革除 localStorage 的长期解决方案。
因为第一版的实现没有做革除,我须要的最现实成果是在 Tab 敞开之后能间接实现革除数据,所以我想到了用 sessionStorage 来解决问题,人造的和 Tab 相关联,Tab 敞开就革除了,完满!接下来须要解决的一个问题就是怎么把数据从一个 Tab 传到新开的 Tab?思考不到几分钟我就想到了计划,答案就是利用 window.opener 属性。我之前怎么就没想到!(╯□╰)
实现
个别咱们关上一个外链的时候,会这样写:
<a href="https://cn.bing.com" target="_blank" rel="noopener noreferrer"> 必应 </a>
这样能够防止关上的外链页面能够通过 window.opener
来非法拜访咱们本人的页面。而咱们当初就是要去掉rel="noopener noreferrer"
,利用这个个性来实现需求。
function getSessionItem(key, remove) {if (!key) {
// thisLocation is defined as a const at the top of the file, just ignore.
throw new Error(`[${thisLocation}] - invalid key: ${key}`);
}
if (remove === undefined) {remove = true;}
let o = window.sessionStorage.getItem(key);
if (!o && window.opener) {o = window.opener.sessionStorage.getItem(key);
}
if (window.opener && remove) {window.opener.sessionStorage.removeItem(key);
}
return o || undefined;
}
function setSessionItem(key, value) {if (!key) {throw new Error(`[${thisLocation}] - invalid key: ${key}`);
}
window.sessionStorage.setItem(key, value);
}
getSessionItem
这个函数会先尝试在本人的 sessionStorage 里获取数据,如果数据不存在则从 opener 的 sessionStorage 获取,接下来就是革除 sessionStorage 里的数据,最初返回。获取到数据之后,再调用 setSessionItem
办法,这样页面从新刷新也能失去数据,能够一直刷新。当用户敞开这个 Tab 之后,数据就主动被浏览器销毁了,达到了咱们想要的成果。
总结
能够看到,写代码的时候,如果没有留神设置 rel="noopener noreferrer"
是很容易呈现平安问题的。而如果是关上咱们本人的页面到能够不必设置,反过来还能够实现相似下面的成果。还有什么?我甚至能够注册一个闭包函数到 window 对象上,当关上新标签之后,新开的 Tab 在须要的时候就能够调用回调函数,告诉原来的 Tab 去解决一些逻辑,同时传输一些数据,甚至能够本人也注册回调函数,把本人的 window 对象传过来,就能够实现不同 Tab 间接双向通信了!