Comment supprimer un élément localStorage lorsque la fenêtre / l'onglet du navigateur est fermé?


403

Mon cas: localStorage avec clé + valeur qui devrait être supprimé lorsque le navigateur est fermé et pas un seul onglet.

Veuillez voir mon code s'il est correct et ce qui peut être amélioré:

//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
Si vous souhaitez effacer le stockage local à la fermeture du navigateur, je vous demanderais pourquoi vous l'utilisez.
Dunhamzzz

16
Vous pouvez avoir des objets de stockage locaux et de session - j'utiliserais sessionStorage pour les valeurs de session. Btw, définir une valeur sur undefined ne le supprime pas ou ne le supprime pas de localStorage, il définit simplement sa valeur sur undefined.
kennebec

2
@kennebec - Le réglage sur undefinedremplacerait cependant l'élément précédemment stocké. Mais oui, l'utilisation .removeItem()est plus appropriée.
nnnnnn

2
il suffit d'utiliser sessionStorage au lieu de localStorage
Alberto Acuña

2
Utilisez-le localStorage.clear(); si vous souhaitez effacer tout l'espace de stockage.
Black Mamba

Réponses:


802

devrait être fait comme ça et non avec l'opérateur de suppression:

localStorage.removeItem(key);

1
Pourquoi ne pouvons-nous pas utiliser exactement l'opérateur de suppression? D'après mes tests, il semble que cela delete localStorage.keyfonctionne aussi bien que localStorage.removeItem(key). Il me semble plus clair d'utiliser la suppression lorsque je règle mes variables comme localStorage.key = 1plutôt que localStorage.setItem('key', 1).
Aust

6
Si cela fonctionne, vous pouvez techniquement l'utiliser. Mais étant donné que removeItem est fourni en tant que fonction membre, il semble logique de l'utiliser plutôt que d'exécuter un comportement potentiellement indéfini à l'aide d'un opérateur distinct.
kungphu

@kungphu gardez à l'esprit que l'on peut toujours (accidentellement) le faire localStorage.removeItem = null;, se faisant localStorage.removeItem(key);une idée potentiellement mauvaise.
skeggse

31
Je ne vois pas en quoi c'est une éventualité raisonnable à prévoir. Le fait qu'un langage permette aux gens de faire des choses destructrices ne signifie pas que vous devez adopter des façons non standard d'utiliser les bibliothèques comme défense contre l'utilisation abusive du langage. Si vous ou vos collègues développeurs ne comprenez pas la différence entre l'appel et l'attribution, vous avez des problèmes bien plus importants que la meilleure façon de supprimer des éléments de localStorage.
kungphu

3
@skeggse c'est exactement pourquoi c'est une mauvaise idée d'écrire localStorage.key = 1en premier lieu - pour éviter ce genre d'accidents
Jivan

114

Utiliser avec windowun mot-clé global: -

 window.localStorage.removeItem('keyName');

6
pourquoi utiliser Window Object? localStorage.removeItem(key)fonctionne tout simplement bien.
Pardeep Jain


Cette solution fonctionne-t-elle vraiment pour IE 11? Veuillez suggérer. J'ai des problèmes avec le code angulaire 5.
Karan

95

Vous pouvez utiliser l' beforeunloadévénement en JavaScript.

En utilisant vanilla JavaScript, vous pourriez faire quelque chose comme:

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

Cela supprimera la clé avant la fermeture de la fenêtre / de l'onglet du navigateur et vous invite à confirmer l'action de fermeture de la fenêtre / de l'onglet. J'espère que cela résout votre problème.

REMARQUE: la onbeforeunloadméthode doit renvoyer une chaîne.


C'était vraiment utile. Il pourrait être agréable d'accepter la réponse (même après tout ce temps).
Richard Morgan

8
@dhsto VanillaJS est du JavaScript simple :) Regardez ici: Qu'est-ce que VanillaJS? .
Bharat Khatri du

1
Un problème est que cela est appelé même si vous naviguez sur la même page, pas seulement lorsque l'onglet est fermé, ce qui n'est peut-être pas ce qui est prévu. Note latérale: le retour non défini de onbeforeunload désactivera le message qui s'affiche lors du déchargement.
Stan Bondi

Que se passe-t-il si l'utilisateur souhaite rester sur la page et que vous supprimez déjà le stockage local? De plus, la solution ne fonctionne pas sur Chrome et IE11
oracleruiz

Pourquoi ne pas utiliser sessionStorage alors?
Sachin Prasad

94

Vous devez utiliser sessionStorage à la place si vous souhaitez que la clé soit supprimée à la fermeture du navigateur.


3
C'est la meilleure réponse; sessionStorageest le remède à ce que le demandeur décrit.
Benny

8
+1 pour le mentionner sessionStorage, mais le projet du rédacteur en chef du W3C dit: `` La durée de vie d'un contexte de navigation peut être indépendante de la durée de vie du processus de l'agent utilisateur lui-même, car l'agent utilisateur peut prendre en charge la reprise des sessions après un redémarrage. ''
Tamás

28
Le problème avec 'sessionStorage' est qu'il n'est pas stocké lorsque vous ouvrez un nouvel onglet, par exemple avec ctrl cliquez sur un lien. J'ai besoin d'un lol hybride localStorage / sessionStorage.
Edwin Stoteler

3
@EdwinStoteler Moi aussi. Je suis un peu confus à ce qu'ils pensaient quand ils l'ont conçu de cette façon. J'ai vraiment besoin d'accéder essentiellement à un stockage de navigateur en mémoire uniquement qui est détruit à la fermeture du navigateur. Je souhaite stocker des informations sensibles d'une manière accessible sur tout un domaine, mais je ne souhaite pas que ces informations atteignent des disques durs.
BT

19

Essayez d'utiliser

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

J'espère que cela fonctionne pour toi


2
voulez-vous effacer le stockage local complet? si c'est le cas, utilisez simplementlocalStorage.clear();
Rafael Marques

c'était clair ce que je veux en question - touche seulement supprimer + valeur
Yosef

12
Cela nettoiera tout le stockage local. mauvaise solution!
Emmy

12

Il existe un cas d'utilisation très spécifique dans lequel toute suggestion d'utiliser sessionStorage au lieu de localStorage n'aide pas vraiment. Le cas d'utilisation serait quelque chose d'aussi simple que d'avoir quelque chose stocké pendant qu'au moins un onglet est ouvert, mais l'invalider si vous fermez le dernier onglet restant. Si vous avez besoin que vos valeurs soient enregistrées sous forme de tableau croisé et de fenêtre, sessionStorage ne vous aide que si vous compliquez votre vie avec des auditeurs, comme j'ai essayé. En attendant, localStorage serait parfait pour cela, mais il fait le travail «trop bien», car vos données y attendront même après un redémarrage du navigateur. J'ai fini par utiliser un code et une logique personnalisés qui tirent parti des deux.

Je préfère expliquer puis donner du code. Enregistrez d'abord ce dont vous avez besoin dans localStorage, puis créez également dans localStorage un compteur qui contiendra le nombre d'onglets que vous avez ouverts. Cela augmentera à chaque chargement de la page et diminuera à chaque déchargement de la page. Vous pouvez faire votre choix ici des événements à utiliser, je suggère «charger» et «décharger». Au moment du déchargement, vous devez effectuer les tâches de nettoyage que vous souhaitez lorsque le compteur atteint 0, ce qui signifie que vous fermez le dernier onglet. Voici la partie délicate: je n'ai pas trouvé de moyen fiable et générique pour faire la différence entre un rechargement de page ou une navigation dans la page et la fermeture de l'onglet. Donc, si les données que vous stockez ne sont pas quelque chose que vous pouvez reconstruire lors du chargement après avoir vérifié qu'il s'agit de votre premier onglet, alors vous ne pouvez pas le supprimer à chaque rafraîchissement. Au lieu de cela, vous devez stocker un indicateur dans sessionStorage à chaque chargement avant d'augmenter le compteur d'onglets. Avant de stocker cette valeur, vous pouvez vérifier si elle a déjà une valeur et si ce n'est pas le cas, cela signifie que vous chargez dans cette session pour la première fois, ce qui signifie que vous pouvez faire le nettoyage à la charge si cela La valeur n'est pas définie et le compteur est 0.


En réponse au "pourquoi ne pas utiliser sessionStorage?" , également depuis w3schools.com/html/html5_webstorage.asp : "window.sessionStorage - stocke les données pour une session (les données sont perdues lorsque l'onglet est fermé)". Donc, la réponse est juste cela. sessionStorage est inutile si vous voulez quelque chose de persistant même dans le cas d'utilisation que j'ai décrit.
Solthun

3
Je pense que la meilleure implémentation pour cela serait un service browserWatcher qui déclenche essentiellement des événements que d'autres composants peuvent écouter (par exemple, ouverture du navigateur, fermeture du navigateur, chargement du navigateur, déchargement du navigateur, etc. et masquer tous ces détails d'implémentation à l'intérieur) . Chaque composant peut décider quels événements il doit gérer pour faire son travail. Ma seule question serait de savoir ce qui se passe si l'alimentation est coupée sur la machine ou quelque chose, alors ces propriétés resteront dans localStorage la prochaine fois que le navigateur sera ouvert ?
pQuestions123

11

utiliser sessionStorage

L'objet sessionStorage est égal à l'objet localStorage, sauf qu'il stocke les données pour une seule session. Les données sont supprimées lorsque l'utilisateur ferme la fenêtre du navigateur.

L'exemple suivant compte le nombre de fois qu'un utilisateur a cliqué sur un bouton, dans la session en cours:

Exemple

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
Les données sont supprimées à la fermeture de l'onglet du navigateur.
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
Lorsque vous répondez à une ancienne question, votre réponse serait beaucoup plus utile aux autres utilisateurs de StackOverflow si vous incluez un contexte pour expliquer en quoi votre réponse est utile, en particulier pour une question qui a déjà une réponse acceptée. Voir: Comment écrire une bonne réponse .
Tân

Ça me semble assez clair
Giorgio Tempesta

4

Bien que certains utilisateurs aient déjà répondu à cette question, je donne un exemple de paramètres d'application pour résoudre ce problème.

J'ai eu le même problème. J'utilise le module https://github.com/grevory/angular-local-storage dans mon application angularjs. Si vous configurez votre application comme suit, elle enregistrera la variable dans le stockage de session au lieu du stockage local. Par conséquent, si vous fermez le navigateur ou fermez l'onglet, le stockage de session sera supprimé automatiquement. Vous n'avez pas besoin de faire quoi que ce soit.

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

J'espère que cela vous aidera.


4

Vous avez le choix entre cinq méthodes:

  • setItem (): Ajouter une clé et une valeur à localStorage
  • getItem (): Récupère une valeur par la clé de localStorage
  • removeItem (): Supprimer un élément par clé de localStorage
  • clear (): efface tout localStorage
  • key (): passé un nombre pour récupérer la nième clé d'un localStorage

Vous pouvez utiliser clear (), cette méthode lorsqu'elle est invoquée efface tout le stockage de tous les enregistrements de ce domaine. Il ne reçoit aucun paramètre.

window.localStorage.clear();

3

Voici un test simple pour voir si vous avez la prise en charge du navigateur lorsque vous travaillez avec le stockage local:

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

Cela a fonctionné pour moi comme prévu (j'utilise Google Chrome). Adapté de: http://www.w3schools.com/html/html5_webstorage.asp .


3

Je ne pense pas que la solution présentée ici soit 100% correcte, car l'événement window.onbeforeunload est appelé non seulement lorsque le navigateur / l'onglet est fermé (QUI EST REQUIS), mais également pour tous les autres événements. (QUI POURRAIT NE PAS ÊTRE REQUIS)

Voir ce lien pour plus d'informations sur la liste des événements pouvant déclencher window.onbeforeunload: -

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


Vous avez peut-être raison, mais ce que vous avez publié est toujours un commentaire, pas une réponse.
nnnnnn du


3

Après avoir examiné cette question 6 ans après qu'elle a été posée, j'ai constaté qu'il n'y avait toujours pas de réponse suffisante à cette question; qui devrait atteindre tous les objectifs suivants:

  • Effacer le stockage local après avoir fermé le navigateur (ou tous les onglets du domaine)
  • Préserver le stockage local entre les onglets, si au moins un onglet reste actif
  • Préserver le stockage local lors du rechargement d'un seul onglet

Exécutez ce morceau de javascript au début de chaque chargement de page afin d'atteindre les objectifs ci-dessus:

((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');

Edit: L'idée de base ici est la suivante:

  1. Lors du démarrage à partir de zéro, le stockage de session se voit attribuer un identifiant aléatoire dans une clé appelée tabid
  2. Le stockage local est ensuite défini avec une clé appelée tabscontenant un objet ces cléstabid est définie sur 1.
  3. Lorsque l'onglet est déchargé, le stockage local tabsest mis à jour en un objet contenanttabid défini sur 0.
  4. Si l'onglet est rechargé, il est d'abord déchargé et repris. Étant donné que la clé de stockage de session tabidexiste, ainsi que la tabsclé de stockage locale avec une sous-clé detabid stockage local n'est pas non plus effacée.
  5. Lorsque le navigateur est déchargé, tout le stockage de session sera effacé. Lors de la reprise, le stockage de session tabidn'existera plus et un nouveau tabidsera généré. Étant donné que le stockage local n'a pas de sous-clé pour cela tabid, ni aucun autretabid (toutes les sessions ont été fermées), il est effacé.
  6. Lors d'un nouvel onglet créé, un nouveau tabidest généré dans le stockage de session, mais comme au moins un tabs[ tabid] existe, le stockage local n'est pas effacé

1
Si le navigateur plante, cependant, le window.onbeforeunloadne sera pas appelé et le local tabs[tabid]ne sera pas défini sur 0 => le stockage local ne sera plus effacé. Je pense qu'un chien de garde serait plus approprié dans ce cas, au lieu d'écrire 1 lors du chargement des onglets, vous devriez écrire l'horodatage actuel. Ensuite, dans la partie réduire, vous devez affirmer le retard car cet horodatage n'est pas trop grand ou le remplacer par 0 s'il l'est. De cette façon, vous ne dépendez pas de l'appel réel de onbeforeunload. L'onglet a juste besoin de réinitialiser le chien de garde de temps en temps pour maintenir l'existence du stockage local.
xryl669

1

C'est une vieille question, mais il semble qu'aucune des réponses ci-dessus ne soit parfaite.

Dans le cas où vous souhaitez stocker l'authentification ou toute information sensible qui n'est détruite que lorsque le navigateur est fermé, vous pouvez compter sur sessionStorageet localStoragepour la transmission des messages croisés.

Fondamentalement, l'idée est:

  1. Vous démarrez à partir d'aucun onglet précédent ouvert, donc vos localStorageet sessionStoragesont vides (sinon, vous pouvez effacer le localStorage). Vous devrez enregistrer un écouteur d'événement de message sur le localStorage.
  2. L'utilisateur authentifie / crée une information sensible sur cet onglet (ou tout autre onglet ouvert sur votre domaine).
  3. Vous mettez sessionStorageà jour le pour stocker les informations sensibles, utilisez le localStoragepour stocker ces informations, puis supprimez-les (vous ne vous souciez pas de la durée ici, car l'événement a été mis en file d'attente lorsque les données ont changé). Tout autre onglet ouvert à ce moment sera rappelé lors de l'événement de message, et mettra à jour son sessionStorageavec les informations sensibles.
  4. Si l'utilisateur ouvre un nouvel onglet sur votre domaine, celui- sessionStorageci sera vide. Le code devra définir une clé dans le localStorage(par exemple:) req. Tout (tous) les autres onglets seront rappelés dans l'événement de message, voir cette clé, et peuvent répondre avec les informations sensibles de leur sessionStorage(comme dans 3), s'ils en ont.

Veuillez noter que ce schéma ne dépend pas d'un window.onbeforeunloadévénement fragile (puisque le navigateur peut être fermé / planté sans que ces événements soient déclenchés). De plus, la durée pendant laquelle les informations sensibles sont stockées sur lelocalStorage durée pendant laquelle est très petite (puisque vous vous fiez à la détection des modifications transitoires pour les événements de message croisé), il est donc peu probable que de telles informations sensibles fuient sur le disque dur de l'utilisateur.

Voici une démo de ce concept: http://jsfiddle.net/oypdwxz7/2/


Merci pour la retouche xryl669, tu as fait un bon point. Quand j'y pense maintenant, serait-il préférable d'utiliser un travailleur Web partagé? developer.mozilla.org/en-US/docs/Web/API/SharedWorker au cas où la prise en charge actuelle du navigateur ne serait pas un problème
Hacktisch

Oui, vous pouvez utiliser un SharedWorker ou un BroadcastChannel (ou un localStorage comme celui-ci), bien que les deux premiers ne soient pas disponibles dans Edge. Fondamentalement, toute méthode qui est un tableau croisé ou une fenêtre croisée fonctionnerait. La difficulté est d'en trouver un qui fonctionne partout avec le minimum de tracas.
xryl669

1

Il n'y a pas une telle façon de détecter la fermeture du navigateur, donc vous ne pouvez probablement pas supprimer localStorage à la fermeture du navigateur, mais il existe une autre façon de gérer les choses que vous pouvez utiliser sessionCookies car il détruira après la fermeture du navigateur.C'est ce que j'ai implémenté dans mon projet.


1

Vous pouvez simplement utiliser sessionStorage. Parce que sessionStorage permet d'effacer toutes les valeurs de clé lorsque la fenêtre du navigateur sera fermée.

Voir ici: SessionStorage- MDN


-5

vous pouvez essayer le code suivant pour supprimer le stockage local:

delete localStorage.myPageDataArr;

29
Ce n'est pas la bonne façon de supprimer une clé localStorage. Vous devez utiliser localStorage.removeItem(key);pour supprimer une clé.
MT.

1
Devrait utiliser localStorage.removeItem (clé); pas le mot-clé à supprimer.
Rob Evans

@MT. Pourquoi ne pas utiliser delete? J'ai essayé, et ça marche. Y a-t-il un effet secondaire ou quelque chose que nous ne devrions pas utiliser pour supprimer? Je vous remercie.
user1995781

2
@ user1995781 en utilisant deleten'est pas la meilleure pratique danslocalStorage
justmyfreak

1
@justmyfreak C'est une non-réponse
alvitawa
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.