背景

▲ 上半年解决”url 传参方式, 因参数过长导致 url 过长”问题时想到使用 sessionStorage 缓存参数,今天突然发现这个办法在新项目里不管用:虽然新开的 Tab 与源页面在相同的域,但源页面设置的 sessionStorage 在新开 Tab 中读取不到。

▲ 网上查找如何在 Tab 之间共享 sessionStorage 的方案,排名第一的搜索结果居然是通过 localStorage 做中转

分析与解决

■ 印象里 sessionStorage 与 localStorage 的区别只有生命周期不同,查看MDN 中对 sessionStorage 的说明才发现自己认知的漏洞,从以下截图描述(特别是红框位置)可见 sessionStorage 还有以下特性:
(1)浏览器打开新 Tab 的时候会为其单独创建一份新的 sessionStorage。
(2)相同域下不同 Tab 的 sessionStorage 是相互独立的。

■ 但为何自己当时可以在新开的 Tab 读取到源页面的 sessionStorage 呢,从截图中蓝框位置描述看到了线索:当前页面的 sessionStorage 是有办法拷贝到新开 Tab 中的。

■ 查找拷贝 sessionStorage 的方法看到了设置 rel=”opener”的方法,将其中提问者给出的demo修改如下就可以在新开 Tab 读到 sessionStorage 啦。

1
2
3
4
5
6
7
8
9
10
function openPageInNewTab() {
const link = document.createElement('a');
link.target = '_blank';
link.href = '/';
link.setAttribute('visibility', 'hidden');
link.setAttribute('rel', 'opener'); // 增加此行
document.body.appendChild(link);
link.click();
link.remove();
}

额外信息

○ Chrome 从版本 89 开始,打开新 Tab 时不再默认将当前 sessionStorage 拷贝到新开 Tab,详见:Chrome Feature: Stop cloning sessionStorage for windows opened with noopener

○ 查了之前项目代码,那时候是使用 window.open()函数实现的新开 Tab。经测试依然有效,也就是当前通过 window.open()函数打开新 Tab 时,仍然会将当前 sessionStorage 拷贝到新开 Tab。

○ 携带 rel=”opener”要注意使用场景,防止安全类问题