sessionStorage 可以在多个 tab 间共享数据吗?

 

近期组内招人面试,在问问题的过程中提到了 localStorage 和 sessionStorage, 因为在开发 Electron 的过程中经常使用 localStorage 来存储数据,方便多个窗口共享,就顺便问了一下 sessionStorage 是否也可以,印象里是不可以的,面试者给我的答案是同源情况下是可以的。我也不确定,于是整理如下。

先总结一个第一个问题, localStoage 和 sessionStorage 的区别? 以下是 chatgpt 给的答案,我觉得很准确,就直接引用了

localStorage和sessionStorage是HTML5提供的两种客户端存储数据的方式。 它们的主要区别在于数据的生命周期和作用域。 localStorage的数据在浏览器关闭后仍然保留,因此具有长期存储的特性。它的作用域是在同一域名下的所有页面共享,即使是不同的标签页或窗口也可以访问相同的数据。 而sessionStorage的数据只在当前会话(即当前标签页或窗口)中有效。当会话结束时,数据将被清除。它的作用域限定在当前标签页或窗口,不同的标签页或窗口之间无法共享数据。

上述引用直接把标题的答案给了出来, sessionStorage 在不同的标签页和窗口之间无法共享数据,那真的是这个样子的吗?我们写 demo 验证一下

使用 react 搭建一个项目,配置两个路由, /about/inbox

<Router>
  <Routes>
    <Route path="/" element={<App></App>} />
    <Route path="/about" element={<About></About>} />
    <Route path="/inbox" element={<Inbox></Inbox>} />
  </Routes>
</Router>

<About> 组件实现如下, 只有一个方法, 读取 sessionStorage 和 localStorage

function About() {
  const getStorage = () => {
    console.log('sessionStorage', sessionStorage.getItem('session-name'));
    console.log('localStorage', localStorage.getItem('local-name'));
  }
  return (
    <div>
      <h2>About</h2>
      <button onClick={getStorage}>获取 storege</button>
    </div>
  );
}

<Inbox> 组件实现如下, 有三个方法,分别是设置、修改、清空 storage, 两种打开新 tab 的方式,一种是 window.open, 一种是 a 链接

function Inbox() {

  const setStorage = () => {
    sessionStorage.setItem('session-name', 'yach');
    localStorage.setItem('local-name', 'yach');
  }

  const modifyStorage = () => {
    sessionStorage.setItem('session-name', 'yach-modify');
    localStorage.setItem('local-name', 'yach-modify');
  }

  const clearStorage = () => {
    sessionStorage.clear();
    localStorage.clear();
  }

  const onOpen = () => {
    window.open('http://localhost:3000/#/about')
  }

  return (
    <div>
    <h2>Inbox</h2>
    <button onClick={setStorage}>设置 storege</button>
    <button onClick={modifyStorage}>修改 storage</button>
    <button onClick={clearStorage}>清空 storage</button>
    <button onClick={onOpen}>window.open</button>
    {/* <Link to='/about' target="_blank">link</Link> */}
    <a href="http://localhost:3000/#/about" target="_blank" rel="noreferrer">a</a>
    </div>
  );
}

demo 已经写完, 那我们就开始验证吧

  1. 同时打开两个 tab,分别加载 /about 和 /inbox, inbox 设置storage, about 获取, 结果如下
    sessionStorage null
    localStorage yach
    

    此处可以得出结论, sessionStorage 数据在多窗口和多 tab 下不共享

  2. 先打开 /inbox, 设置一下 storage, 在通过 window.open 打开 /about 获取, 结果如下
    sessionStorage yach
    localStorage yach
    

这次就能获取到, 那到底能不能共享呢? 经过网上查阅得出如下结论

在一个新的 tab 或者窗口打开页面就会创建一个具有顶级浏览器上下文的新 session

sessionStorage 不可以在多个窗口或者 tab 间共享数据,但是当新的页面是通过 window.open 打开的,那么新的页面就会复制上一个页面的 sessionStorage 到新的页面中。

有人说通过链接方式打开,也会复制一份新的 sessionStorage, 通过上面 demo 试了一下,发现不行。目前只有通过 window.open 打开新页面会复制一份新的 sessionStorage