啊,原来sessionStorage是这样的

458 阅读4分钟

最近需要完成一个分屏和脱离主窗口的功能,因为我把是否分屏的状态保存到了sessionStorage中,所以以前的功能时发现了一个小问题,在通过window.open打开的窗口会复用主窗口的sessionStorage,这就有奇怪了。sessionStorage的状态不是随着主窗口的存在而存在吗?

通过 window.open 打开的窗口复用当前窗口的 sessionStorage,是由浏览器的同源策略和页面上下文继承机制决定的。以下是详细解释:

sessionStorag的基本规律

  • 作用域sessionStorage 的作用域限定在 同源(协议+域名+端口) 下的单个浏览器标签页或窗口。
  • 生命周期:数据仅在当前会话(标签页或窗口)有效,关闭标签页后数据销毁。
  • 隔离性:默认情况下,不同标签页或窗口的 sessionStorage 是相互隔离的。

那结合window.open又有啥魔法呢

通过 window.open(url, '_blank') 打开的新窗口如果满足下面两个条件,可以继承原窗口的 sessionStorage

  • 同源:新窗口加载的 URL 与原窗口同源
  • 由脚本触发:新窗口通过 JavaScript 代码打开。这个也就可以区分是用户手动(右键菜单选择“在新标签页打开链接”)创建的还是有用户触发代码创建的

注意:window.open还可以指定第三个参数,用于在窗口当开tab页,只要同源也是可以共享sessionStorage的。

为何会出现这种现象呢?

  • 浏览上下文继承
    通过 window.open 打开的窗口,可能被视为原窗口的“子窗口”。浏览器会将原窗口的 sessionStorage 复制到新窗口,但后续修改会独立(复制后两者不再同步)。

  • 规范与实现差异
    HTML5 规范未明确规定此行为,因此不同浏览器实现可能不同。例如:

    • Chrome:复制 sessionStorage
    • Firefox:不复制,新窗口的 sessionStorage 为空。
    • Safari:行为可能随版本变化。

总结

window.open 复用 sessionStorage 是浏览器对脚本打开 同源窗口的一种特殊处理,旨在保留上下文状态。但需注意不同浏览器的实现差异。

sessionStorage.gif

还有哪些方式可以共享主页面的sessionStorage呢

通过 <iframe> 嵌入的同源页面

父页面通过 <iframe> 嵌入同源的子页面

<iframe> 内嵌的页面与父页面共享相同的 sessionStorage,因为它们属于同一浏览上下文。如果用户手动在新标签页打开 <iframe> 的URL,sessionStorage 将不共享。

<!-- 不共享sessionStorage -->
<!-- <iframe src="https://juejin.cn/user/2225067267204935" frameborder="0"></iframe> -->
<!-- 共享 ,因为同源-->
<iframe src="http://127.0.0.1:5500/b.html" frameborder="1"></iframe>

通过 javascript: 导航的同源页面

通过 javascript: 协议在地址栏跳转或通过链接跳转。

某些浏览器可能会将此视为同一会话上下文(类似 window.open),但此行为不统一且可能被拦截。

  <a href="javascript:window.open('http://127.0.0.1:5500/b.html')">打开新标签页</a>

image.png

通过 target="_blank" 的同源链接(需特定条件)

在 <a> 标签中使用 target="_blank" 打开同源页面,且添加 rel="opener"

新标签页通过 window.opener 保持与父页面的关联,某些浏览器可能共享 sessionStorage。现代浏览器(如Chrome)默认启用 rel="noopener",需显式禁用才能保持关联。所以需要设置rel="opener"可以通过window.opener获取打开当前页面的window引用,必须设置rel="opener"

<a href="https://same-origin.com/page" target="_blank" rel="opener">打开新标签页</a>

以上众多方法都是只有在同源的状态下且是同一个浏览器上下文中才会进行共享。

往期年度总结

往期文章

专栏文章