Tab页面互相通信

原文地址
这是一篇拖更了一个月的文章,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 直接双向通信了!

原文链接:segmentfault.com

上一篇:5G“乍到”,图扑带你了解室内定位可视化的实现与新突破
下一篇:谈一谈你对this的了解?Can you talk about your understanding of this ?

相关推荐

  • (详解)从浏览器输入 URL 到页面展示过程

    引言 对于面试常问的从浏览器输入 URL 到页面渲染过程发生了什么?,我想大家都或多或少能说出一二。但是,其实这个问题很有深度,而你是否回答的有深度,在很大程度上会影响到面试官对你的印象。

    4 个月前
  • 魔方实时通信一对一音视频组件

    魔方实时通信/协作引擎(Web SDK)是一个全能力的实时云端协作引擎 魔方实时通信,请点击这个(https://www.shixincube.com/) 继上一个im聊天组件增加了发动语音,语音...

    2 年前
  • 高德地图+vue实现页面点击绘制多边形及多边形切割拆分

    最终效果 (/public/upload/7732e1e729bfcd99f99f56cd04ac17b1) 技术栈 项目中使用到的技术 高德基于vue的vueamap,组件使用的elemen...

    2 个月前
  • 项目中的导航栏搜索及搜索页面的思路

    项目背景 今天项目里的实习生在做搜索功能时,导航栏的搜索框与搜索页面的搜索框,在内容上竟然是各自独立的。。。。。 无论他怎么鼓捣,在搜索栏上进行搜索,搜索页面都没有任何反应。

    3 个月前
  • 页面间通信--使用storage事件保持多tab页共享轮询请求的数据

    业务场景 最近接到一个优化需求,某页面会轮询请求两个接口获取未读消息的数量,但是当用户同时在多个tab打开了页面的话,这些页面都会进行轮询请求,有用户打开tab页太多,1分钟请求了几千次,触发了风控,...

    2 个月前
  • 页面进入后台如何关闭背景音乐

    之前在做小程序的时候遇到一个问题:小程序中有一个webview页面,这个页面中用iframe嵌套了一个H5页面,这个H5页面中有背景音乐,背景音乐播放的情况下,点击小程序右上角退出的小圆圈背景音乐仍然...

    1 年前
  • 页面跳转的归纳

    前端工作有很多地方需要页面跳转,有很多种实现方法,这里做一下归纳。 HTML标签 一般形式上可以用target="blank": 历史跳转 ...

    2 年前
  • 页面跳转时,点击上报丢失问题解析

    背景 最近在工作中,遇到了页面跳转时点击上报丢失的问题,突出表现在微信ios的webview上,上报后直接跳转的失败率达到了惊人的93%。喝口水压压惊,开始逐步分析问题的发生。

    2 年前
  • 页面跳转中的安全问题

    最近参与了一小部分安全排查,涉及到一些前端编码安全问题,记个小tip。 1.Http请求头中的Referer 0a2b525c5fc64af362821115x362.png@900090f.p...

    8 个月前
  • 页面负载启动自举模型

    zanzuBrandon(https://stackoverflow.com/users/4398000/zanzu)提出了一个问题:Launch Bootstrap Modal on page lo...

    2 年前

官方社区

扫码加入 JavaScript 社区