You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

本地主机新窗口登录导致LocalStorage原有数据被覆盖的原因

问题原因分析与解决方案

这个问题我太熟了!本质是LocalStorage的同源共享特性在搞鬼:

  • LocalStorage是基于同源策略的存储机制,同一域名(包括localhost)下的所有浏览器窗口、标签页都会共享同一个LocalStorage存储空间。
  • 当你在新窗口发起登录请求时,代码里的localStorage.setItem('token', response.token)localStorage.setItem('user', $sjUser)会直接覆盖掉原有窗口中存储的同名key值,旧窗口的LocalStorage数据自然就被新登录的内容替换了。

针对性解决方案

方案1:改用SessionStorage(最简单直接)

SessionStorage是窗口级别的独立存储,每个窗口/标签页拥有完全独立的存储空间,不同窗口之间不会互相干扰。修改你的代码即可:

// 登录时存储数据
sessionStorage.setItem('token', response.token);
// ...
sessionStorage.setItem('user', $sjUser);

// 获取数据时
$jUser = JSON.parse(sessionStorage.user)

缺点:关闭窗口后SessionStorage数据会被自动清除,适合不需要跨窗口持久保存的会话场景。

方案2:给存储Key添加唯一会话标识

如果需要跨窗口保留数据但又不想互相覆盖,可以给每个会话生成唯一ID,将其作为存储Key的一部分:

// 生成唯一会话ID(时间戳+随机数组合,保证唯一性)
const sessionId = Date.now() + '_' + Math.random().toString(36).substr(2, 9);

// 登录时存储数据
localStorage.setItem(`token_${sessionId}`, response.token);
localStorage.setItem(`user_${sessionId}`, $sjUser);
// 把会话ID存在当前窗口的SessionStorage,用来后续读取对应数据
sessionStorage.setItem('currentSessionId', sessionId);

// 获取数据时
const currentSessionId = sessionStorage.getItem('currentSessionId');
$jUser = JSON.parse(localStorage.getItem(`user_${currentSessionId}`))

这种方式需要额外管理会话ID,适合需要持久化多会话数据的场景。

方案3:监听Storage事件实现多窗口状态同步

如果你的需求是多窗口保持登录状态同步(而不是避免覆盖),可以监听storage事件,当某个窗口修改LocalStorage时,其他窗口自动更新自身状态:

// 在main.js中添加监听逻辑
window.addEventListener('storage', function(e) {
  if (e.key === 'user' || e.key === 'token') {
    // 重新读取最新数据并更新页面UI
    $jUser = JSON.parse(localStorage.user);
    $('#frame #sidepanel #profile-img').attr('src', $jUser.avatar);
    $('#frame #sidepanel #profile .wrap #full-name').text($jUser.first_name + ' ' + $jUser.last_name);
  }
});

这个方案适合需要多窗口同步登录状态的场景。

内容的提问来源于stack exchange,提问作者July333

火山引擎 最新活动