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>
相关推荐
哆啦刘小洋5 分钟前
HTML Day04
前端·html
再学一点就睡35 分钟前
JSON Schema:禁锢的枷锁还是突破的阶梯?
前端·json
从零开始学习人工智能2 小时前
FastMCP:构建 MCP 服务器和客户端的高效 Python 框架
服务器·前端·网络
烛阴2 小时前
自动化测试、前后端mock数据量产利器:Chance.js深度教程
前端·javascript·后端
好好学习O(∩_∩)O2 小时前
QT6引入QMediaPlaylist类
前端·c++·ffmpeg·前端框架
敲代码的小吉米2 小时前
前端HTML contenteditable 属性使用指南
前端·html
testleaf2 小时前
React知识点梳理
前端·react.js·typescript
站在风口的猪11082 小时前
《前端面试题:HTML5、CSS3、ES6新特性》
前端·css3·html5
Xiao_die8882 小时前
前端八股之CSS
前端·css
每天都有好果汁吃3 小时前
基于 react-use 的 useIdle:业务场景下的用户空闲检测解决方案
前端·javascript·react.js