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>
相关推荐
我要洋人死1 小时前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai2 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9152 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼3 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風7 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#