【问题标题】:How to delete a localStorage item when the browser window/tab is closed?关闭浏览器窗口/选项卡时如何删除 localStorage 项目?
【发布时间】:2012-04-14 03:40:30
【问题描述】:

我的案例:带有键 + 值的 localStorage 应该在浏览器关闭而不是单个选项卡时删除。

请查看我的代码是否正确以及可以改进的地方:

//create localStorage key + value if not exist
if(localStorage){
   localStorage.myPageDataArr={"name"=>"Dan","lastname"=>"Bonny"}; 
}

//when browser closed - psedocode
$(window).unload(function(){
  localStorage.myPageDataArr=undefined;
});

【问题讨论】:

  • 如果您想在浏览器关闭时清除本地存储,我会质疑您使用它的原因。
  • 您可以同时拥有本地和会话存储对象——我会使用 sessionStorage 来存储会话值。顺便说一句,将值设置为 undefined 不会将其删除,或者将其从 localStorage 中删除,它只是将其值设置为 undefined。
  • @kennebec - 设置为undefined 会覆盖之前存储的项目。但是是的,使用.removeItem() 更合适。
  • 只使用 sessionStorage 而不是 localStorage
  • 如果要清除整个存储空间,请使用localStorage.clear();

标签: javascript jquery html local-storage


【解决方案1】:

应该这样做,而不是使用删除运算符:

localStorage.removeItem(key);

【讨论】:

  • 为什么我们不能使用删除操作符呢?从我的测试来看,delete localStorage.key 似乎和localStorage.removeItem(key) 一样好用。当我将变量设置为 localStorage.key = 1 而不是 localStorage.setItem('key', 1) 时,使用 delete 似乎更清楚。
  • 如果它有效,你可以在技术上使用它。但是考虑到 removeItem 是作为成员函数提供的,使用它似乎是合乎逻辑的,而不是使用单独的运算符遇到潜在的未定义行为。
  • @kungphu 请记住,人们总是可以(不小心)做localStorage.removeItem = null;,这使得localStorage.removeItem(key); 成为一个潜在的糟糕想法。
  • 我看不出这是一个合理的应急计划。一种语言允许人们做破坏性的事情这一事实并不意味着您应该采用非标准的方式来使用库来防止滥用该语言。如果您或您的其他开发人员不了解调用和赋值之间的区别,那么您面临的问题要比如何最好地从 localStorage 中删除项目要大得多。
  • @skeggse 这就是为什么首先写localStorage.key = 1 是个坏主意——以避免这种事故
【解决方案2】:

window 全局关键字一起使用:-

 window.localStorage.removeItem('keyName');

【讨论】:

  • 为什么要使用窗口对象?只需 localStorage.removeItem(key) 工作正常。
  • 这个解决方案真的适用于 IE 11 吗?请建议。我在 Angular 5 代码中遇到了这个问题。
【解决方案3】:

如果您希望在浏览器关闭时删除密钥,则应使用 sessionStorage。

【讨论】:

  • 这是最好的答案; sessionStorage 是对提问者描述的补救措施。
  • +1 用于提及sessionStorage,但W3C Editor's Draft 表示:'浏览上下文的生命周期可能与实际用户代理进程本身的生命周期无关,因为用户代理可能支持重启后恢复会话。'
  • “sessionStorage”的问题是当您打开一个新选项卡时它不会被存储,例如使用 ctrl 单击一个链接。我需要一个 localStorage/sessionStorage 混合大声笑。
  • @EdwinStoteler 我也是。当他们以这种方式设计时,我有点困惑他们在想什么。我真的需要访问一个内存中的浏览器存储,当浏览器关闭时它会被破坏。我想以一种可以在整个域中访问的方式存储敏感信息,但我不希望该信息进入任何硬盘。
【解决方案4】:

您可以在 JavaScript 中使用beforeunload 事件。

使用原生 JavaScript,您可以执行以下操作:

window.onbeforeunload = function() {
  localStorage.removeItem(key);
  return '';
};

这将在关闭浏览器窗口/选项卡之前删除密钥,并提示您确认关闭窗口/选项卡操作。希望能解决你的问题。

注意:onbeforeunload 方法应该返回一个字符串。

【讨论】:

  • 这确实很有用。接受答案可能会很好(即使经过这么长时间)。
  • @dhsto VanillaJS 是纯 JavaScript :) 看这里:What is VanillaJS?
  • 一个问题是即使您在同一页面上导航也会调用它,而不仅仅是在关闭选项卡时调用,这可能不是预期的。旁注:从 onbeforeunload 返回 undefined 将禁用卸载时显示的消息。
  • 如果用户想留在页面上而您已经删除了本地存储会发生什么?该解决方案也不适用于 Chrome 和 IE11
  • 那为什么不使用 sessionStorage 呢?
【解决方案5】:

有一个非常具体的用例,其中使用 sessionStorage 而不是 localStorage 的任何建议都没有真正的帮助。 用例就像在至少打开一个选项卡时存储一些东西一样简单,但是如果您关闭剩余的最后一个选项卡,它就会失效。 如果您需要将值保存在交叉选项卡和窗口中,除非您像我尝试过的那样让听众的生活变得复杂,否则 sessionStorage 对您没有帮助。 与此同时,localStorage 将是完美的,但它做得“太好了”,因为即使在重新启动浏览器后,您的数据也会在那里等待。 我最终使用了一个自定义代码和逻辑来利用两者。

我宁愿解释然后给出代码。首先将您需要的内容存储在 localStorage 中,然后在 localStorage 中创建一个计数器,该计数器将包含您打开的选项卡的数量。 每次页面加载时都会增加,每次页面卸载时都会减少。您可以在这里选择要使用的事件,我建议“加载”和“卸载”。 在您卸载时,您需要在计数器达到 0 时执行您想要执行的清理任务,这意味着您正在关闭最后一个选项卡。 棘手的部分来了:我还没有找到一种可靠且通用的方法来区分页面重新加载或页面内的导航与选项卡的关闭之间的区别。 因此,如果您存储的数据不是您可以在检查这是您的第一个选项卡后在加载时重建的数据,那么您无法在每次刷新时将其删除。 相反,您需要在每次加载时在 sessionStorage 中存储一个标志,然后再增加选项卡计数器。 在存储这个值之前,你可以检查它是否已经有一个值,如果没有, 这意味着您是第一次加载到此会话中,这意味着如果未设置此值且计数器为 0,您可以在加载时进行清理。

【讨论】:

  • 回答“为什么不使用 sessionStorage?”方法,也来自w3schools.com/html/html5_webstorage.asp:“window.sessionStorage - 存储一个会话的数据(关闭选项卡时数据丢失)”。所以答案就是这样。即使在我描述的用例中,如果您想要持久的东西,sessionStorage 也是无用的。
  • 我认为最好的实现是 browserWatcher 服务,它基本上触发其他组件可以监听的事件(即浏览器打开、浏览器关闭、浏览器加载、浏览器卸载等。并将所有这些实现细节隐藏在其中。每个组件都可以决定它需要处理哪些事件才能完成其工作。我唯一的问题是如果机器断电或其他什么会发生什么,那么这些属性将保留在 localStorage下次打开浏览器不是吗?
【解决方案6】:

尝试使用

$(window).unload(function(){
  localStorage.clear();
});

希望这对你有用

【讨论】:

  • 这将清理整个本地存储。糟糕的解决方案!
【解决方案7】:

使用会话存储

sessionStorage 对象与 localStorage 对象相同,只是它只存储一个会话的数据。当用户关闭浏览器窗口时,数据被删除。

以下示例计算用户在当前会话中单击按钮的次数:

例子

if (sessionStorage.clickcount) {
    sessionStorage.clickcount = Number(sessionStorage.clickcount) + 1;
} else {
    sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "You have clicked the button " +
sessionStorage.clickcount + " time(s) in this session.";

【讨论】:

  • 数据在浏览器标签关闭时被删除。
  • sessionStorage 不在选项卡之间共享;它不等于 localStorage。
【解决方案8】:
localStorage.removeItem(key);  //item

localStorage.clear(); //all items

【讨论】:

  • 在回答一个老问题时,如果您包含一些上下文来解释您的答案如何提供帮助,那么您的答案将对其他 StackOverflow 用户更有用,特别是对于已经有一个已接受答案的问题。请参阅:How do I write a good answer
【解决方案9】:

有五种方法可供选择:

  • setItem():向本地存储添加键和值
  • getItem():从 localStorage 中获取 key 的值
  • removeItem():从 localStorage 中按键删除项目
  • clear():清除所有本地存储
  • key():传递了一个数字来检索 localStorage 的第 n 个键

您可以使用 clear(),调用此方法时会清除该域的所有记录的整个存储。它不接收任何参数。

window.localStorage.clear();

【讨论】:

    【解决方案10】:
    for (let i = 0; i < localStorage.length; i++) {
        if (localStorage.key(i).indexOf('the-name-to-delete') > -1) {
            arr.push(localStorage.key(i));
        }
    }
    
    for (let i = 0; i < arr.length; i++) {
        localStorage.removeItem(arr[i]);
    }
    

    【讨论】:

      【解决方案11】:

      8.5 年过去了,最初的问题从未真正得到回答。

      当浏览器关闭而不是单个标签时。

      此基本代码 sn-p 将为您提供两全其美的体验。仅在浏览器会话期间持续存在的存储(类似于 sessionStorage),但也可在选项卡之间共享(localStorage)。

      它纯粹是通过 localStorage 来做到这一点的。

      function cleanup(){
          // place whatever cleanup logic you want here, for example:
          // window.localStorage.removeItem('my-item')
      }
      
      function tabOpened(){
          const tabs = JSON.parse(window.localStorage.getItem('tabs'))
          if (tabs === null) {
              window.localStorage.setItem('tabs', 1)
          } else {
              window.localStorage.setItem('tabs', ++tabs)
          }
      }
      
      function tabClosed(){
          const tabs = JSON.parse(window.localStorage.getItem('tabs'))
          if (tabs === 1) {
              // last tab closed, perform cleanup.
              window.localStorage.removeItem('tabs')
              cleanup()
          } else {
              window.localStorage.setItem('tabs', --tabs)
          }
      }
      
      window.onload = function () {
          tabOpened();
      }
      
      window.onbeforeunload = function () {
          tabClosed();
      }
      
      

      【讨论】:

      • 我认为这不能正常工作。想想这个场景:首先,用户转到网站的主页。现在选项卡设置为 1。然后用户单击链接并导航到站点上的另一个页面 => 调用 onbeforeunload 处理程序来清理 localStorage。
      • 我明白你的意思;我与 SPA 合作的时间太长了……我现在很喜欢,但我回家后会更新答案。
      【解决方案12】:

      为什么不使用 sessionStorage?

      “sessionStorage 对象与 localStorage 对象相同,只是它只存储一个会话的数据。当用户关闭浏览器窗口时,数据将被删除。”

      http://www.w3schools.com/html/html5_webstorage.asp

      【讨论】:

        【解决方案13】:

        虽然有些用户已经回答了这个问题,但我还是举一个应用程序设置的例子来解决这个问题。

        我遇到了同样的问题。我在我的 angularjs 应用程序中使用 https://github.com/grevory/angular-local-storage 模块。如果您按如下方式配置您的应用程序,它将把变量保存在会话存储中而不是本地存储中。因此,如果您关闭浏览器或关闭选项卡,会话存储将被自动删除。你不需要做任何事情。

        app.config(function (localStorageServiceProvider) {
          localStorageServiceProvider
          .setPrefix('myApp')
          .setStorageType('sessionStorage')
        });
        

        希望它会有所帮助。

        【讨论】:

          【解决方案14】:

          这是一个简单的测试,看看您在使用本地存储时是否支持浏览器:

          if(typeof(Storage)!=="undefined") {
            console.log("localStorage and sessionStorage support!");
            console.log("About to save:");
            console.log(localStorage);
            localStorage["somekey"] = 'hello';
            console.log("Key saved:");
            console.log(localStorage);
            localStorage.removeItem("somekey");  //<--- key deleted here
            console.log("key deleted:");
            console.log(localStorage);
            console.log("DONE ===");
          } else {
            console.log("Sorry! No web storage support..");
          }
          

          它按预期对我有用(我使用谷歌浏览器)。 改编自:http://www.w3schools.com/html/html5_webstorage.asp

          【讨论】:

            【解决方案15】:

            我不认为这里提出的解决方案是 100% 正确的,因为 window.onbeforeunload 事件不仅在浏览器/选项卡关闭时被调用(这是必需的),而且在所有其他几个事件中也被调用。 (可能不需要)

            有关可以触发 window.onbeforeunload 的事件列表的更多信息,请参阅此链接:-

            http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx

            【讨论】:

            • 您可能是对的,但您发布的内容仍然是评论,而不是答案。
            【解决方案16】:

            这个问题被问了6年之后再看,我发现这个问题仍然没有足够的答案;这应该实现以下所有:

            • 关闭浏览器(或域的所有选项卡)后清除本地存储
            • 如果至少有一个选项卡保持活动状态,则跨选项卡保留本地存储
            • 重新加载单个选项卡时保留本地存储

            在每个页面加载开始时执行这段 javascript 以实现上述目的:

            ((nm,tm) => {
                const
                        l = localStorage,
                        s = sessionStorage,
                        tabid = s.getItem(tm) || (newid => s.setItem(tm, newid) || newid)((Math.random() * 1e8).toFixed()),
                        update = set => {
                            let cur = JSON.parse(l.getItem(nm) || '{}');
                            if (set && typeof cur[tabid] == 'undefined' && !Object.values(cur).reduce((a, b) => a + b, 0)) {
                                l.clear();
                                cur = {};
                            }
                            cur[tabid] = set;
                            l.setItem(nm, JSON.stringify(cur));
                        };
                update(1);
                window.onbeforeunload = () => update(0);
            })('tabs','tabid');
            

            编辑:这里的基本思路如下:

            1. 从头开始时,会话存储在名为tabid 的键中分配一个随机ID
            2. 然后使用名为 tabs 的键设置本地存储,其中包含将键 tabid 设置为 1 的对象。
            3. 卸载选项卡时,本地存储的tabs 更新为包含tabid 设置为0 的对象。
            4. 如果选项卡被重新加载,它首先被卸载并恢复。由于会话存储的密钥tabid存在,本地存储tabs具有子密钥tabid的密钥也存在,因此本地存储不会被清除。
            5. 卸载浏览器时,所有会话存储将被清除。当恢复会话存储时,tabid 将不再存在,并且将生成一个新的tabid。由于本地存储没有此tabid 的子键,也没有任何其他tabid(所有会话都已关闭),因此将其清除。
            6. 在新创建的标签页上,会话存储中会生成一个新的tabid,但由于至少存在一个tabs[tabid],因此不会清除本地存储

            【讨论】:

            • 但是,如果浏览器崩溃,window.onbeforeunload 将不会被调用,并且本地的tabs[tabid] 不会被设置为 0 => 本地存储将永远不会被清除。我认为在这种情况下看门狗会更合适,而不是在标签加载时写 1,你应该写当前时间戳。然后在减少部分,您应该断言延迟,因为该时间戳不是太大,如果是,则替换为 0。这样,您就不必依赖onbeforeunload 的实际调用。该选项卡只需要不时重置看门狗以保持本地存储存在。
            【解决方案17】:

            您可以简单地使用 sessionStorage。因为 sessionStorage 允许在关闭浏览器窗口时清除所有键值。

            请看:SessionStorage- MDN

            【讨论】:

              【解决方案18】:

              这是一个老问题,但上面的答案似乎都不是完美的。

              如果您想存储身份验证或任何仅在关闭浏览器时被破坏的敏感信息,您可以依靠sessionStoragelocalStorage 进行交叉表消息传递。

              基本上,这个想法是:

              1. 您从没有打开之前的选项卡进行引导,因此您的localStoragesessionStorage 都是空的(如果没有,您可以清除localStorage)。您必须在 localStorage 上注册一个消息事件侦听器。
              2. 用户在此选项卡(或在您的域中打开的任何其他选项卡)上验证/创建敏感信息。
              3. 您更新sessionStorage 来存储敏感信息,并使用localStorage 来存储此信息,然后将其删除(您不必关心这里的时间,因为数据更改时事件已排队)。当时打开的任何其他选项卡都将在消息事件中被回调,并将使用敏感信息更新其sessionStorage
              4. 如果用户在您的域上打开一个新选项卡,其sessionStorage 将为空。代码必须在localStorage 中设置一个键(例如:req)。任何(所有)其他选项卡都将在消息事件中被回调,查看该键,并且可以使用来自其sessionStorage(如 3 中)的敏感信息进行回答,如果他们有的话。

              请注意,此方案不依赖于脆弱的window.onbeforeunload 事件(因为浏览器可以在不触发这些事件的情况下关闭/崩溃)。此外,敏感信息存储在localStorage 上的时间非常短(因为您依赖transcients 更改检测来检测交叉表消息事件),因此此类敏感信息不太可能泄漏到用户的硬盘上。

              这是这个概念的演示:http://jsfiddle.net/oypdwxz7/2/

              【讨论】:

              • 感谢您的编辑 xryl669,您提出了一个很好的观点。当我现在考虑这个问题时,最好使用共享网络工作者吗? developer.mozilla.org/en-US/docs/Web/API/SharedWorker 以防当前浏览器支持不是问题
              • 是的,您可以使用 SharedWorker 或 BroadcastChannel(或类似这样的 localStorage),尽管前两个在 Edge 中不可用。基本上,任何跨表、跨窗口的方法都可以使用。困难在于找到一种在任何地方都能以最少的麻烦工作的产品。
              【解决方案19】:

              没有这样的方法来检测浏览器关闭,所以你可能无法在浏览器关闭时删除 localStorage,但是还有另一种方法可以处理你可以使用 sessionCookies 的东西,因为它会在浏览器关闭后销毁。这是我在我的项目。

              【讨论】:

                【解决方案20】:
                    if(localStorage.getItem("visit") === null) {
                      localStorage.setItem('visit', window.location.hostname);
                      console.log(localStorage.getItem('visit'));
                    } 
                      else if(localStorage.getItem('visit') == 'localhost'){
                            console.log(localStorage.getItem('visit'));
                      }
                    else {
                     console.log(localStorage.getItem('visit'));
                    }
                   $(document).ready(function(){
                      $("#clickme").click(function(){
                         localStorage.setItem('visit', '0');
                      });
                   });  
                   window.localStorage.removeItem('visit');
                

                【讨论】:

                • 欢迎来到 Stackoverflow!你能在代码中添加一个解释吗?
                【解决方案21】:

                这将解决对象的问题。

                localStorage.removeItem('key');
                

                或者

                localStorage.setItem('key', 0 );  
                

                【讨论】:

                  【解决方案22】:
                  window.addEventListener('beforeunload', (event) => {
                  
                      localStorage.setItem("new_qus_id", $('.responseId').attr('id'));
                  
                      var new_qus_no = localStorage.getItem('new_qus_id');
                      console.log(new_qus_no);
                  
                  });
                  
                  if (localStorage.getItem('new_qus_id') != '') {
                      var question_id = localStorage.getItem('new_qus_id');
                  } else {
                      var question_id = "<?php echo $question_id ; ?>";
                  }
                  

                  【讨论】:

                  • 欢迎来到 Stackoverflow!你能在代码中添加一个解释吗?
                  【解决方案23】:

                  您可以尝试以下代码来删除本地存储:

                  delete localStorage.myPageDataArr;
                  

                  【讨论】:

                  • 这不是删除 localStorage 键的正确方法。您应该使用localStorage.removeItem(key); 删除密钥。
                  • 应该使用localStorage.removeItem(key);不是 delete 关键字。
                  • @MT。为什么不使用delete?我试过了,它有效。是否有任何副作用或任何我们不应该使用删除的东西?谢谢。
                  • @user1995781 使用delete 不是localStorage 中的最佳实践
                  • @justmyfreak 那不是答案
                  猜你喜欢
                  • 1970-01-01
                  • 2016-12-31
                  • 2014-01-31
                  • 2014-02-09
                  • 2011-01-05
                  • 1970-01-01
                  相关资源
                  最近更新 更多