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>
相关推荐
over69723 分钟前
用 React Context 实现全局主题切换:从零搭建暗黑/亮色模式系统
前端·react.js·面试
ycgg26 分钟前
深入理解 AbortSignal:前端异步操作取消的原生方案
前端
妮妮喔妮27 分钟前
前端字节面试大纲
前端·面试·职场和发展
白兰地空瓶29 分钟前
告别“千里传荔枝”:React useContext 打造跨层级通信“任意门”
前端·react.js
恋猫de小郭37 分钟前
Flutter 小技巧之帮网友理解 SliverConstraints overlap
android·前端·flutter
小oo呆39 分钟前
【自然语言处理与大模型】LangChainV1.0入门指南:核心组件Structured Output
前端·javascript·easyui
Mapmost39 分钟前
【高斯泼溅】3DGS城市模型从“硬盘杀手”到“轻盈舞者”?看我们如何实现14倍压缩
前端
AC赳赳老秦1 小时前
农业智能化:DeepSeek赋能土壤与气象数据分析,精准预测病虫害,守护丰收希望
java·前端·mongodb·elasticsearch·html·memcache·deepseek
囊中之锥.1 小时前
《HTML 网页构造指南:从基础结构到实用标签》
前端·html
饼饼饼1 小时前
从 0 到 1:前端 CI/CD 实战(第二篇:用Docker 部署 GitLab)
前端·自动化运维