关闭浏览器窗口/选项卡时如何删除localStorage项目?


403

我的情况:具有键+值的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;
});

32
如果您想在浏览器关闭时清除本地存储,请问您使用它的原因。
Dunhamzzz 2012年

16
您可以同时具有本地和会话存储对象-我将使用sessionStorage作为会话值。顺便说一句,将值设置为undefined不会删除它,也不会将其从localStorage中删除,它只是将其值设置为undefined。
肯尼伯2012年

2
@kennebec-设置为undefined会覆盖以前存储的项目。但是可以,使用.removeItem()更合适。
nnnnnn

2
只需使用sessionStorage而不是localStorage
AlbertoAcuña17年

2
使用localStorage.clear(); ,如果你想清除整个存储。
黑色曼巴

Answers:


802

应该这样,而不是使用delete运算符:

localStorage.removeItem(key);

1
为什么我们不能完全使用delete运算符?根据我的测试,似乎delete localStorage.key效果和一样好localStorage.removeItem(key)。在我将变量设置为localStorage.key = 1而不是时,使用delete似乎更清晰localStorage.setItem('key', 1)
2015年

6
如果可行,您可以从技术上使用它。但是考虑到removeItem作为成员函数提供,使用它似乎是合乎逻辑的,而不是使用单独的运算符来运行可能未定义的行为。
kungphu '16

@kungphu请记住,一个人总是可以(偶然地)做localStorage.removeItem = null;,这localStorage.removeItem(key);可能是个糟糕的主意。
skeggse

31
我不认为这是一个合理的应急计划。语言可以使人们做破坏性的事情,这并不意味着您应该采用非标准的方式使用库来防止滥用该语言。如果您或您的其他开发人员不了解调用和分配之间的区别,那么您将面临比如何最好地从localStorage删除项目更大的问题。
kungphu '16

3
@skeggse这就是为什么首先写一个坏主意的原因localStorage.key = 1-避免这种情况
Jivan


95

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

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

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

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

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


这确实是有用的。接受答案可能会很好(即使在所有这些时间之后)。
理查德·摩根

8
@dhsto VanillaJS是普通的JavaScript :)看这里:什么是VanillaJS?
巴拉特·哈特里

1
一个问题是,即使您在同一页面上导航,也不仅是在关闭选项卡时(这可能不是预期的),它都会被调用。旁注:从onbeforeunload返回undefined将禁用在卸载时显示的消息。
斯坦·邦迪

如果用户希望停留在页面上并且您已经删除了本地存储该怎么办?另外,该解决方案在Chrome和IE11上
不起作用

那为什么不使用sessionStorage呢?
萨钦·普拉萨德

94

如果要在浏览器关闭时删除密钥,则应改用sessionStorage。


3
这是最好的答案;sessionStorage是对问询者描述的补救措施。
本尼

8
+1代表提及sessionStorage,但W3C编辑器的草案说:“浏览上下文的生存期可能与实际用户代理进程本身的生存期无关,因为用户代理可能支持重启后恢复会话。”
塔马斯2014年

28
“ sessionStorage”的问题是,当您打开新选项卡时,例如,使用ctrl单击链接,它不会存储。我需要一个localStorage / sessionStorage混合大声笑。
Edwin Stoteler 2015年

3
@EdwinStoteler我也是。我有点困惑他们以这种方式设计时的想法。实际上,我确实需要访问仅内存的浏览器存储,而该存储在浏览器关闭时会被破坏。我想以一种可以在整个域中访问的方式存储敏感信息,但是我不希望该信息碰到任何硬盘。
BT

19

尝试使用

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

希望这对你有用


2
您要清除完整的localStorage吗?如果是这样的话,请使用localStorage.clear();
拉斐尔·马克斯

它很清楚我想要的是什么-仅删除键+值
Yosef 2012年

12
这将清除整个本地存储。不好的解决方案!
艾美奖

12

在一个非常特定的用例中,使用sessionStorage而不是localStorage的任何建议都没有真正的帮助。用例就像在打开至少一个选项卡时存储内容一样简单,但是如果关闭最后一个选项卡,该用例将无效。如果您需要跨表和窗口保存值,那么除非像我尝试过的那样,使用监听器使生活变得复杂,否则sessionStorage不会为您提供帮助。同时,localStorage对此非常适合,但是它做得“很好”,因为即使重新启动浏览器,您的数据也会在那里等待。我最终使用了自定义代码和逻辑,两者都可以利用。

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


作为“为什么不使用sessionStorage?”的答案 同样来自w3schools.com/html/html5_webstorage.asp的方法:“ window.sessionStorage-存储一个会话的数据(关闭选项卡时数据丢失)”。所以答案就是这样。如果您想要持久的东西,即使在我描述的用例中,sessionStorage也没用。
Solthun 2015年

3
我认为最好的实现方法是使用browserWatcher服务,该服务基本上会触发其他组件可以监听的事件(即,打开浏览器,关闭浏览器,加载浏览器,卸载浏览器等),并将所有这些实现细节隐藏在其中每个组件都可以决定完成其工作所需处理的事件,我唯一的问题是,如果机器或某些设备断电,会发生什么情况,那么下次打开浏览器时,这些属性将保留在localStorage中。 ?
pQuestions123

11

使用sessionStorage

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.";

1
在浏览器选项卡关闭时,数据被删除。
Kosmonaft

7
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]);
}

5
localStorage.removeItem(key);  //item

localStorage.clear(); //all items

1
当回答一个旧问题时,如果您包含一些上下文来解释您的答案如何帮助您的答案,则对于其他StackOverflow用户将更加有用,尤其是对于已经接受了答案的问题。请参阅:如何写一个好的答案

对我来说看起来足够清楚
Giorgio Tempesta

4

尽管有些用户已经回答了这个问题,但我在此提供了一个应用程序设置示例来解决此问题。

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

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

希望它会有所帮助。


4

有五种方法可供选择:

  • setItem():将键和值添加到localStorage
  • getItem():通过密钥从localStorage检索值
  • removeItem():通过密钥从localStorage删除项目
  • clear():清除所有localStorage
  • key():传递数字以检索localStorage的第n个键

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

window.localStorage.clear();

3

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

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..");
}

它按预期对我有效(我使用的是Google Chrome)。改编自:http : //www.w3schools.com/html/html5_webstorage.asp


3

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

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

http://msdn.microsoft.com/zh-CN/library/ms536907(VS.85).aspx


您可能是对的,但您发布的内容只是评论而不是答案。
nnnnnn 2013年


3

在问了这个问题六年后,我发现仍然没有足够的答案。它应该实现以下所有目的:

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

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

1
但是,如果浏览器崩溃,window.onbeforeunload将不会调用,并且本地tabs[tabid]不会设置为0 =>本地存储将不再被清除。我认为在这种情况下,看门狗会更合适,而不是在加载标签时写1,而应该编写当前时间戳。然后在归约部分中,您应该声明延迟,因为该时间戳不是太大,或者如果为0,则将其替换。这样,您就不必依赖实际调用了onbeforeunload。该选项卡仅需要不时重置看门狗以保持本地存储的存在。
xryl669

1

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

如果您要存储身份验证或仅在关闭浏览器时销毁的任何敏感信息,则可以依赖交叉表消息sessionStoragelocalStorage进行传递。

基本上,这个想法是:

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

请注意,此方案不依赖于window.onbeforeunload易碎事件(因为可以在不触发这些事件的情况下关闭/崩溃浏览器)。此外,敏感信息在存储在计算机上的时间localStorage非常短(因为您依赖跨科学消息事件的科学变更检测),因此此类敏感信息不太可能在用户的硬盘驱动器上泄漏。

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


感谢您对xryl669的编辑,您的观点很不错。当我现在考虑这个问题时,也许最好使用共享的Web worker?developer.mozilla.org/en-US/docs/Web/API/SharedWorker的情况下,当前的浏览器支持是不是一个问题
Hacktisch

是的,尽管前两个在Edge中不可用,但是您可以使用SharedWorker或BroadcastChannel(或类似的localStorage)。基本上,可以使用跨选项卡,跨窗口的任何方法。困难在于找到一种在任何地方都可轻松解决的问题。
xryl669

1

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



-5

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

delete localStorage.myPageDataArr;

29
这不是删除localStorage密钥的正确方法。您应该使用localStorage.removeItem(key);删除密钥。
MT。

1
应该使用localStorage.removeItem(key); 不是删除关键字。
Rob Evans

@公吨。为什么不使用delete?我尝试了,并且有效。是否有任何副作用或我们不应该使用delete的任何内容?谢谢。
user1995781 2014年

2
@ user1995781使用delete不是最佳实践localStorage
justmyfreak 2014年

1
@justmyfreak这不是一个答案
alvitawa '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.