sessionStorage会话周期,了解清楚它的边界情况

sessonStorage属性是允许前端访问和存储值的一个对象,和localStorage一样使用,只是它们的生命周期有所不同,所以我要明确的了解sessionStorage的会话周期边界情况,去避免一些使用引起的bug。

1、正常的我们的理解,sessionStorage会在我们打开浏览器访问网页一直保持,刷新重新加载页面数据都会保持着,直到关闭该标签页

html 复制代码
<html>
    <body>
        <h1>Hello, World!</h1>
        <p>This is a test page A.</p>

        <!-- 点击跳转到B -->
        <a href="B.html">Go to test page B</a>
        <script>
          console.log("Hello from test page A!");
          // 存储一个session
          sessionStorage.setItem("message", "Hello from test page A!");
        </script>
    </body>
</html>
html 复制代码
<html>
    <body>
        <h1>Hello, World!</h1>
        <p>This is a test page B.</p>

        <script>
          console.log("Hello from test page B!");
          console.log(sessionStorage)
        </script>
    </body>
</html>

由A存储的session值,点击跳转到B后,B仍能访问到

2、换一种方式,如果是使用_blank打开新标签页呢?很尴尬,访问不到值了

html 复制代码
<html>
    <body>
        <h1>Hello, World!</h1>
        <p>This is a test page A.</p>

        <!-- 点击跳转到新标签页B -->
        <a target="_blank" href="B.html">Go to test page B</a>
        <script>
          console.log("Hello from test page A!");
          // 存储一个session
          sessionStorage.setItem("message", "Hello from test page A!");
        </script>
    </body>
</html>
  • 换种方式,通过js脚本window.open去打开新标签页,奇怪的发现,又可以访问到值了
html 复制代码
<html>
    <body>
        <h1>Hello, World!</h1>
        <p>This is a test page A.</p>

        <!-- 脚本跳转 -->
        <button onclick="go()">Go to test page B</button>
        <script>
          console.log("Hello from test page A!");
          // 存储一个session
          sessionStorage.setItem("message", "Hello from test page A!");

          function go() {
            window.open('/B.html')
          }
        </script>
    </body>
</html>

思考为何a标签跳转打开不行呢??

网上搜索看看了,原来a标签默认rel="noopener",这种情况下不携带sessionStorage的值,需要配置rel="opener"

html 复制代码
<html>
<body>
    <h1>Hello, World!</h1>
    <p>This is a test page A.</p>

    <!-- 点击跳转到B -->
    <a target="_blank" href="B.html" rel="opener">Go to test page B</a>
    <script>
      console.log("Hello from test page A!");
      // 存储一个session
      sessionStorage.setItem("message", "Hello from test page A!");
    </script>
</body>
</html>

3、 换种方式,直接复制A页的访问连接,新建一个标签页打开,还是很尴尬,依旧访问不到值了

4、 再换种方式,将A页再新窗口打开,这时只是指标签页的移动,值能够访问到

综上情况看,我们需要注意了,会话不是在关闭浏览器前一直保留,而是标签页关闭就会销毁,有很多伙伴包括我刚开始接触前端都认为session在浏览器关闭前一直存储着,这就是边界理解错了,很可能在开发的时候写出bug,而且还需要主要新打开的标签页,通过代码打开的可以访问到,但是要注意a标签和window.open的不同,而人为打开的新标签无非共享访问

讲讲我为啥会遇到这样的误解,很早之前做后端的时候用于存储登录记录,后台有个session,记得前辈说关闭浏览器就会失效,我也就一知半解没深究,后面就与前端的sessionStorage搞混了,这两个并不是一个东西,后台存储的session有个sessionId,这个是存储在cookie中的,请求时会带着,后台根据sessionIdsession取值,判断是否登录,而通过对cookie的过期时间配置就可以达到浏览器关闭cookie销毁,从而session失效。

最后

思考我们该如何处理人为打开新标签页呢???

其实呢,比如详情页,这些打开新标签页都应该根据接口响应获取数据,而不是通过sessionStorage存储从别的地方带进详情页

不过就问题处理问题吧,前端该怎么尽量改进优化呢?我这里讲讲我的想法,通过SharedWorker来处理

js 复制代码
// worker.js
const set = new Set()
onconnect = event => {
  const port = event.ports[0]
  set.add(port)


  // 接收信息
  port.onmessage = e => {
    // 广播信息
    set.forEach(p => {
      p.postMessage(e.data)
    })
  }
}
html 复制代码
<html>
<body>
    <h1>Hello, World!</h1>
    <p>This is a test page A.</p>

    <!-- 点击跳转到B -->
    <a target="_blank" href="B.html">Go to test page B</a>

    <button onclick="go()">Go to test page B</button>
    <script>
      console.log("Hello from test page A!");
      // 存储一个session
      sessionStorage.setItem("message", "Hello from test page A!");

      function go() {
        window.open("/B.html")
      }

      var worker = new SharedWorker("./worker.js")
      worker.port.onmessage = function(e) {
        var result = JSON.parse(e.data);
        if (result.from === "B" && result.type === "init") {
          worker.port.postMessage(JSON.stringify({ from: "A", type: "sessionStorage", sessionStorage: sessionStorage }));
        }
      }
    </script>
</body>
</html>
html 复制代码
<html>
<body>
    <h1>Hello, World!</h1>
    <p>This is a test page B.</p>

    <script>
      console.log("Hello from test page B!");
      console.log(sessionStorage)

      var worker = new SharedWorker("./worker.js")
      worker.port.onmessage = function(e) {
        var result = JSON.parse(e.data);
        console.log(result.sessionStorage)
        if (result.from === "A" && result.type === "sessionStorage") {
          for (var key in result.sessionStorage) {
            sessionStorage.setItem(key, result.sessionStorage[key]);
          }
        }
      }
      worker.port.postMessage(JSON.stringify({
        type: "init",
        from: "B"
      }))
    </script>
</body>
</html>
相关推荐
用户479492835691513 分钟前
Vite8来啦,告别 esbuild + Rollup,Vite 8 统一用 Rolldown 了
前端·javascript·vite
枫,为落叶15 分钟前
VueRouter前端路由
前端
踢球的打工仔16 分钟前
前端知识介绍
前端
草字43 分钟前
uniapp 悬浮按钮支持可拖拽。可移动。
前端·javascript·uni-app
一位搞嵌入式的 genius1 小时前
Vue实例挂载:从原理到项目实践的全维度解析
前端·javascript·vue.js·前端框架
waeng_luo1 小时前
[鸿蒙2025领航者闯关] 表单验证与用户输入处理最佳实践
开发语言·前端·鸿蒙·鸿蒙2025领航者闯关·鸿蒙6实战·开发者年度总结
0思必得01 小时前
[Web自动化] 开发者工具应用(Application)面板
运维·前端·python·自动化·web自动化·开发者工具
m0_740043731 小时前
Vue Router中获取路由参数d两种方式:$route.query和$route.params
前端·javascript·vue.js
风止何安啊1 小时前
Event Loop 教你高效 “划水”:JS 单线程的“摸鱼”指南
前端·javascript·面试
@菜菜_达1 小时前
goldenLayout布局
前端·javascript