Come eliminare un elemento localStorage quando la finestra / scheda del browser è chiusa?


403

Il mio caso: localStorage con chiave + valore che deve essere eliminato alla chiusura del browser e non a scheda singola.

Si prega di vedere il mio codice se è corretto e cosa può essere migliorato:

//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
Se si desidera cancellare l'archiviazione locale alla chiusura del browser, metterei in dubbio i motivi per cui lo hai utilizzato.
Dunhamzzz,

16
Puoi avere oggetti di archiviazione sia locali che di sessione. Vorrei utilizzare sessionStorage per i valori di sessione. A proposito, l'impostazione di un valore su indefinito non lo elimina, né lo rimuove da localStorage, imposta semplicemente il suo valore su indefinito.
Kennebec,

2
@kennebec - L'impostazione su undefinedsovrascriverà comunque l'elemento precedentemente memorizzato. Ma sì, l'utilizzo .removeItem()è più appropriato.
nnnnnn,

2
usa sessionStorage invece di localStorage
Alberto Acuña il

2
Utilizzare localStorage.clear(); se si desidera cancellare l'intera memoria.
Black Mamba,

Risposte:


802

dovrebbe essere fatto in questo modo e non con l'operatore di eliminazione:

localStorage.removeItem(key);

1
Perché non possiamo usare esattamente l'operatore di eliminazione? Dai miei test, sembra che delete localStorage.keyfunzioni altrettanto bene localStorage.removeItem(key). Mi sembra più chiaro usare delete quando imposto le mie variabili come localStorage.key = 1piuttosto che localStorage.setItem('key', 1).
Aust

6
Se funziona, puoi tecnicamente usarlo. Ma considerando che removeItem viene fornito come una funzione membro, sembra logico usarlo piuttosto che imbattersi in comportamenti potenzialmente indefiniti usando un operatore separato.
Kungphu,

@kungphu tieni presente che si può sempre (accidentalmente) fare localStorage.removeItem = null;, facendo localStorage.removeItem(key);un'idea potenzialmente scadente.
skeggse il

31
Non vedo come sia una ragionevole eventualità da pianificare. Il fatto che una lingua permetta alle persone di fare cose distruttive non significa che dovresti adottare modi non standard di usare le biblioteche come difesa contro l'uso improprio della lingua. Se tu o i tuoi colleghi sviluppatori non capite la differenza tra invocazione e assegnazione, avete problemi molto più grandi rispetto al modo migliore per rimuovere gli articoli da localStorage.
Kungphu,

3
@skeggse questo è esattamente il motivo per cui è una cattiva idea scrivere localStorage.key = 1in primo luogo - per evitare questo tipo di incidenti
Jivan,

114

Utilizzare con windowla parola chiave globale: -

 window.localStorage.removeItem('keyName');

6
perché usare l'oggetto finestra? localStorage.removeItem(key)funziona semplicemente bene.
Pardeep Jain,


Questa soluzione funziona davvero per IE 11? Per favore, suggerisci Sto riscontrando questo problema nel codice angolare 5.
Karan,

95

È possibile utilizzare il beforeunload evento in JavaScript.

Utilizzando JavaScript vaniglia potresti fare qualcosa del tipo:

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

Ciò eliminerà la chiave prima della chiusura della finestra / scheda del browser e richiede di confermare l'azione di chiusura della finestra / scheda. Spero che risolva il tuo problema.

NOTA: il onbeforeunloadmetodo dovrebbe restituire una stringa.


Questo è stato davvero utile. Potrebbe essere bello accettare la risposta (anche dopo tutto questo tempo).
Richard Morgan,

8
@dhsto VanillaJS è semplice JavaScript :) Guarda qui: che cos'è VanillaJS? .
Bharat Khatri,

1
Un problema è che questo viene chiamato anche se si naviga sulla stessa pagina, non solo quando la scheda è chiusa, il che potrebbe non essere quello che si intende. Nota a margine: la restituzione non definita da onbeforeunload disattiverà il messaggio visualizzato durante lo scarico.
Stan Bondi,

Cosa succede se l'utente vuole rimanere nella pagina e hai già eliminato la memoria locale? Inoltre, la soluzione non funziona su Chrome e IE11
oracleruiz,

Perché non usare sessionStorage allora?
Sachin Prasad,

94

È necessario utilizzare sessionStorage invece se si desidera eliminare la chiave alla chiusura del browser.


3
Questa è la risposta migliore; sessionStorageè il rimedio per ciò che descrive il richiedente.
Benny,

8
+1 per menzione sessionStorage, ma l' Editor del W3C Editor dice: "La durata di un contesto di navigazione può non essere correlata alla durata del processo stesso dell'agente utente stesso, poiché l'agente utente può supportare la ripresa delle sessioni dopo un riavvio".
Tamás,

28
Il problema con "sessionStorage" è che non viene archiviato quando si apre una nuova scheda, ad esempio facendo clic con il tasto Ctrl su un collegamento. Ho bisogno di un ibrido localStorage / sessionStorage lol.
Edwin Stoteler,

3
@EdwinStoteler Anche a me. Sono un po 'confuso a cosa stavano pensando quando l'hanno progettato in questo modo. Ho davvero bisogno di accedere essenzialmente a uno spazio di archiviazione del browser in memoria che viene distrutto alla chiusura del browser. Voglio archiviare informazioni riservate in modo che sia possibile accedervi su un intero dominio, ma non voglio che queste informazioni colpiscano alcun disco rigido.
BT,

19

Prova a usare

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

Spero che questo funzioni per te


2
vuoi cancellare l'intero archivio locale? in tal caso basta usarelocalStorage.clear();
Rafael Marques il

era chiaro quello che volevo in questione - chiave solo cancella + valore
Yosef

12
Questo ripulirà l'intero archivio locale. pessima soluzione!
Emmy

12

Esiste un caso d'uso molto specifico in cui qualsiasi suggerimento per utilizzare sessionStorage invece di localStorage non aiuta davvero. Il caso d'uso sarebbe qualcosa di semplice come avere qualcosa memorizzato mentre almeno una scheda è aperta, ma invalidarla se si chiude l'ultima scheda rimasta. Se hai bisogno che i tuoi valori siano salvati su campi incrociati e finestre, sessionStorage non ti aiuta se non ti complichi la vita con gli ascoltatori, come ho provato. Nel frattempo localStorage sarebbe perfetto per questo, ma fa il lavoro "troppo bene", poiché i tuoi dati ti aspetteranno anche dopo il riavvio del browser. Ho finito per usare un codice e una logica personalizzati che sfruttano entrambi.

Preferirei spiegare poi dare il codice. Prima memorizza ciò che ti serve in localStorage, poi anche in localStorage crea un contatore che conterrà il numero di schede che hai aperto. Ciò verrà aumentato ogni volta che la pagina viene caricata e diminuito ogni volta che la pagina viene scaricata. Puoi scegliere qui gli eventi da utilizzare, suggerirei "carica" ​​e "scarica". Al momento dello scarico, devi eseguire le attività di pulizia che desideri quando il contatore raggiunge 0, il che significa che stai chiudendo l'ultima scheda. Ecco la parte difficile: non ho trovato un modo affidabile e generico per dire la differenza tra un ricaricamento della pagina o la navigazione all'interno della pagina e la chiusura della scheda. Quindi, se i dati che memorizzi non sono qualcosa che puoi ricostruire al caricamento dopo aver verificato che questa è la tua prima scheda, quindi non è possibile rimuoverlo ad ogni aggiornamento. Invece è necessario memorizzare un flag in sessionStorage ad ogni carico prima di aumentare il contatore delle schede. Prima di memorizzare questo valore, è possibile verificare se ha già un valore e, in caso contrario, significa che si sta caricando in questa sessione per la prima volta, il che significa che è possibile eseguire la pulizia al caricamento se questo il valore non è impostato e il contatore è 0.


Come risposta al "perché non usare sessionStorage?" approccio, anche da w3schools.com/html/html5_webstorage.asp : "window.sessionStorage - memorizza i dati per una sessione (i dati vengono persi quando la scheda viene chiusa)". Quindi la risposta è proprio questa. sessionStorage è inutile se vuoi qualcosa di persistente anche nella custodia che ho descritto.
Solthun,

3
Sto pensando che la migliore implementazione per questo sarebbe un servizio browserWatcher che fondamentalmente genera eventi che altri componenti possono ascoltare (ad es. Apertura del browser, chiusura del browser, caricamento del browser, scarico del browser ecc. E nascondere tutti questi dettagli di implementazione al suo interno Ogni componente può decidere quali eventi deve gestire per svolgere il proprio lavoro. La mia unica domanda sarebbe cosa succederebbe se l'alimentazione venisse tagliata alla macchina o qualcosa del genere, queste proprietà rimarrebbero in localStorage la prossima volta che il browser viene aperto non ?
pQuestions123

11

usa sessionStorage

L'oggetto sessionStorage è uguale all'oggetto localStorage, tranne per il fatto che memorizza i dati per una sola sessione. I dati vengono eliminati quando l'utente chiude la finestra del browser.

L'esempio seguente conta il numero di volte in cui un utente ha fatto clic su un pulsante, nella sessione corrente:

Esempio

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
I dati vengono eliminati nella chiusura della scheda del browser.
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
Quando rispondi a una vecchia domanda, la tua risposta sarebbe molto più utile per gli altri utenti StackOverflow se includessi un contesto per spiegare come la tua risposta aiuta, in particolare per una domanda che ha già una risposta accettata. Vedi: Come scrivo una buona risposta .
Tân

Mi sembra abbastanza chiaro
Giorgio Tempesta,

4

Sebbene alcuni utenti abbiano già risposto a questa domanda, sto fornendo un esempio di impostazioni dell'applicazione per risolvere questo problema.

Ho avuto lo stesso problema. Sto usando https://github.com/grevory/angular-local-storage modulo nella mia applicazione angularjs. Se configuri l'app nel modo seguente, salverà la variabile nella memoria della sessione anziché nella memoria locale. Pertanto, se si chiude il browser o si chiude la scheda, l'archiviazione della sessione verrà rimossa automaticamente. Non devi fare nulla.

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

Spero che possa essere d'aiuto.


4

Esistono cinque metodi tra cui scegliere:

  • setItem (): aggiungi chiave e valore a localStorage
  • getItem (): recupera un valore dalla chiave da localStorage
  • removeItem (): rimuove un elemento per chiave da localStorage
  • clear (): cancella tutto localStorage
  • key (): passato un numero per recuperare l'ennesima chiave di un localStorage

È possibile utilizzare clear (), questo metodo quando viene richiamato cancella l'intero archivio di tutti i record per quel dominio. Non riceve alcun parametro.

window.localStorage.clear();

3

Ecco un semplice test per vedere se hai il supporto del browser quando lavori con l'archiviazione locale:

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

Ha funzionato per me come previsto (utilizzo Google Chrome). Adattato da: http://www.w3schools.com/html/html5_webstorage.asp .


3

Non credo che la soluzione qui presentata sia corretta al 100% perché l'evento window.onbeforeunload viene chiamato non solo quando il browser / Tab è chiuso (CHE È RICHIESTO), ma anche su tutti gli altri eventi diversi. (CHE NON PUO 'ESSERE RICHIESTO)

Vedere questo collegamento per ulteriori informazioni sull'elenco degli eventi che possono attivare window.onbeforeunload: -

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


Potresti avere ragione, ma comunque quello che hai pubblicato è un commento, non una risposta.
nnnnnn,


3

Dopo aver esaminato questa domanda 6 anni dopo che è stata posta, ho scoperto che non esiste ancora una risposta sufficiente a questa domanda; che dovrebbe raggiungere tutto quanto segue:

  • Cancella archiviazione locale dopo aver chiuso il browser (o tutte le schede del dominio)
  • Conserva memoria locale tra le schede, se almeno una scheda rimane attiva
  • Conserva memoria locale quando si ricarica una singola scheda

Esegui questo pezzo di javascript all'inizio di ogni caricamento della pagina per ottenere quanto sopra:

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

Modifica: l'idea di base qui è la seguente:

  1. Quando si inizia da zero, all'archivio sessioni viene assegnato un ID casuale in una chiave chiamata tabid
  2. La memoria locale viene quindi impostata con una chiave chiamata tabscontenente un oggetto quella chiavetabid è impostata su 1.
  3. Quando la scheda viene scaricata, la memoria locale tabsviene aggiornata in un oggetto contenentetabid impostato su 0.
  4. Se la scheda viene ricaricata, viene prima scaricata e ripresa. Poiché tabidesiste la chiave di archiviazione della sessione , così come la tabschiave di archiviazione locale con una sottochiave ditabid memoria locale non viene cancellata.
  5. Quando il browser viene scaricato, tutta la memoria della sessione verrà cancellata. Quando si riprende, l'archiviazione della sessione tabidnon esiste più e tabidne verrà generata una nuova . Poiché la memoria locale non ha una sottochiave per questo tabid, né nessun altrotabid (tutte le sessioni sono state chiuse), viene cancellata.
  6. Su una nuova scheda creata, tabidviene generata una nuova memoria di sessione, ma poiché esiste almeno una tabs[ tabid], la memoria locale non viene cancellata

1
Se il browser si arresta in modo anomalo, tuttavia, window.onbeforeunloadnon verrà chiamato e il locale tabs[tabid]non verrà impostato su 0 => la memoria locale non verrà più cancellata. Penso che un cane da guardia sarebbe più appropriato in quel caso, invece di scrivere 1 al caricamento della scheda, dovresti scrivere il timestamp corrente. Quindi, nella parte di riduzione, si dovrebbe far valere il ritardo poiché quel timestamp non è troppo grande o sostituirlo con 0 se lo è. In questo modo, non dipendi dall'effettiva chiamata di onbeforeunload. La scheda deve solo reimpostare il watchdog di volta in volta per mantenere l'esistenza di archiviazione locale.
xryl669,

1

Questa è una vecchia domanda, ma sembra che nessuna delle risposte sopra riportate sia perfetta.

Nel caso in cui si desideri archiviare l'autenticazione o qualsiasi informazione sensibile che viene distrutta solo alla chiusura del browser, è possibile fare affidamento su sessionStoragee localStorageper il passaggio di messaggi a campi incrociati.

Fondamentalmente, l'idea è:

  1. Si avvia bootstrap da nessuna scheda precedente aperta, quindi sia tuo localStorageche sessionStoragevuoto sono (in caso contrario, è possibile cancellare il localStorage). Dovrai registrare un listener di eventi messaggio sul localStorage.
  2. L'utente autentica / crea informazioni sensibili su questa scheda (o qualsiasi altra scheda aperta sul tuo dominio).
  3. Si aggiorna sessionStorageper archiviare le informazioni riservate e si utilizza localStorageper archiviare queste informazioni, quindi cancellarle (non ti interessa il tempismo qui, poiché l'evento è stato messo in coda quando i dati sono cambiati). Qualsiasi altra scheda aperta in quel momento verrà richiamata sull'evento messaggio e aggiornerà la lorosessionStorage informazioni sensibili.
  4. Se l'utente apre una nuova scheda sul tuo dominio, sessionStoragesarà vuota. Il codice dovrà impostare una chiave in localStorage(per esempio:) req. Qualsiasi (tutte) altre schede verranno richiamate nell'evento del messaggio, vedrai quella chiave e potranno rispondere con le informazioni sensibili dal loro sessionStorage(come in 3), se ne hanno.

Si noti che questo schema non dipende da window.onbeforeunloadeventi fragili (poiché il browser può essere chiuso / bloccato senza che questi eventi vengano attivati). Inoltre, il tempo in cui le informazioni sensibili vengono archiviate sulocalStorage è molto ridotto (poiché si fa affidamento sul rilevamento delle modifiche dei transitori per l'evento del messaggio a schede incrociate), quindi è improbabile che tali informazioni sensibili perdano sul disco rigido dell'utente.

Ecco una demo di questo concetto: http://jsfiddle.net/oypdwxz7/2/


Grazie per la modifica xryl669, hai fatto un buon punto. Quando sto pensando a questo, sarebbe forse meglio usare un web worker condiviso? developer.mozilla.org/en-US/docs/Web/API/SharedWorker nel caso in cui il supporto del browser corrente non sia un problema
Hacktisch,

Sì, è possibile utilizzare SharedWorker o BroadcastChannel (o un LocalStorage come questo), sebbene i primi due non siano disponibili in Edge. Fondamentalmente, qualsiasi metodo che sia cross tab, cross window, funzionerebbe. La difficoltà sta nel trovarne uno che funzioni ovunque con il minimo fastidio.
xryl669,

1

Non esiste un modo per rilevare la chiusura del browser, quindi probabilmente non è possibile eliminare localStorage alla chiusura del browser, ma esiste un altro modo per gestire le cose che è possibile utilizzare sessionCookies in quanto si distruggerà dopo la chiusura del browser. Questo è quello che ho implementato nel mio progetto.


1

Puoi semplicemente usare sessionStorage. Perché sessionStorage consente di cancellare tutto il valore chiave quando la finestra del browser verrà chiusa.

Vedi qui: SessionStorage- MDN


-5

puoi provare il seguente codice per eliminare la memoria locale:

delete localStorage.myPageDataArr;

29
Questo non è il modo giusto di eliminare una chiave localStorage. Dovresti usare localStorage.removeItem(key);per cancellare una chiave.
MT.

1
Dovrebbe usare localStorage.removeItem (chiave); non la parola chiave delete.
Rob Evans,

@MT. Perché non usare delete? Ho provato e funziona. C'è qualche effetto collaterale o qualcosa che non dovremmo usare Elimina? Grazie.
user1995781

2
@ user1995781 using deletenon è la migliore pratica inlocalStorage
justmyfreak il

1
@justmyfreak Questa è una non-risposta
alvitawa
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.