Jak usunąć element localStorage, gdy okno / karta przeglądarki jest zamknięta?


403

Moja sprawa: localStorage z kluczem + wartością, którą należy usunąć, gdy przeglądarka jest zamknięta, a nie pojedynczą kartę.

Proszę zobaczyć mój kod, jeśli jest poprawny i co można poprawić:

//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
Jeśli chcesz wyczyścić pamięć lokalną po zamknięciu przeglądarki, zapytam o powody korzystania z niej.
Dunhamzzz,

16
Możesz mieć zarówno lokalne, jak i sesyjne obiekty pamięci - używałbym sessionStorage dla wartości sesji. Przy okazji, ustawienie wartości na niezdefiniowaną nie usuwa jej ani nie usuwa z localStorage, po prostu ustawia jej wartość na niezdefiniowaną.
Kennebec

2
@kennebec - Ustawienie undefinedzastępowania wcześniej zapisanego elementu. Ale tak, używanie .removeItem()jest bardziej odpowiednie.
nnnnnn

2
po prostu użyj sessionStorage zamiast localStorage
Alberto Acuña

2
Użyj, localStorage.clear(); jeśli chcesz wyczyścić całe miejsce.
Czarna Mamba,

Odpowiedzi:


802

należy to zrobić w ten sposób, a nie za pomocą operatora delete:

localStorage.removeItem(key);

1
Dlaczego nie możemy dokładnie użyć operatora usuwania? Z moich testów wynika, że delete localStorage.keydziała równie dobrze jak localStorage.removeItem(key). Wydaje mi się, że użycie skasowania jest bardziej zrozumiałe, kiedy ustawiam zmienne jak localStorage.key = 1zamiast localStorage.setItem('key', 1).
Aust

6
Jeśli to działa, możesz go technicznie użyć. Biorąc jednak pod uwagę, że removeItem jest dostarczany jako funkcja składowa, logiczne wydaje się używanie go zamiast działania w potencjalnie nieokreślonym zachowaniu za pomocą osobnego operatora.
kungphu

@ kungphu pamiętaj, że zawsze możesz (przypadkowo) zrobić localStorage.removeItem = null;, co localStorage.removeItem(key);może być kiepskim pomysłem.
skeggse

31
Nie rozumiem, jak zaplanować to rozsądny przypadek. Fakt, że język pozwala ludziom robić destrukcyjne rzeczy, nie oznacza, że ​​powinieneś przyjąć niestandardowe sposoby korzystania z bibliotek jako obrony przed niewłaściwym użyciem języka. Jeśli Ty lub Twoi znajomi programiści nie rozumiecie różnicy między wywołaniem a przypisaniem, macie znacznie większe problemy niż to, jak najlepiej usunąć elementy z localStorage.
kungphu

3
@skeggse właśnie dlatego jest to zły pomysł, aby pisać localStorage.key = 1w pierwszej kolejności - aby uniknąć tego rodzaju wypadków
Jivan


95

Możesz skorzystać z beforeunload zdarzenia w JavaScript.

Za pomocą waniliowego JavaScript możesz zrobić coś takiego:

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

Spowoduje to usunięcie klucza przed zamknięciem okna / karty przeglądarki i monitowanie o potwierdzenie działania zamknięcia okna / karty. Mam nadzieję, że to rozwiąże twój problem.

UWAGA: onbeforeunloadMetoda powinna zwrócić ciąg znaków.


To było naprawdę przydatne. Przyjemnie może być zaakceptować odpowiedź (nawet po tak długim czasie).
Richard Morgan

8
@dhsto VanillaJS to zwykły JavaScript :) Spójrz tutaj: Co to jest VanillaJS? .
Bharat Khatri,

1
Jednym z problemów jest to, że jest to wywoływane, nawet jeśli poruszasz się po tej samej stronie, nie tylko wtedy, gdy karta jest zamknięta, co może być niezgodne z przeznaczeniem. Uwaga dodatkowa: powrót niezdefiniowany z onbeforeunload spowoduje wyłączenie komunikatu wyświetlanego podczas rozładowywania.
Stan Bondi,

Co się stanie, jeśli użytkownik chce pozostać na stronie, a ty już skasowałeś lokalną pamięć? Rozwiązanie nie działa również na Chrome i IE11
oracleruiz

Dlaczego więc nie skorzystać z sessionStorage?
Sachin Prasad

94

Zamiast tego należy użyć sessionStorage, jeśli chcesz, aby klucz został usunięty po zamknięciu przeglądarki.


3
To najlepsza odpowiedź; sessionStoragejest lekarstwem na to, co opisuje pytający.
Benny

8
+1 za wzmiankę sessionStorage, ale wersja robocza edytora W3C mówi: „Czas istnienia kontekstu przeglądania może być niezwiązany z czasem życia samego procesu agenta użytkownika, ponieważ agent użytkownika może obsługiwać wznawianie sesji po ponownym uruchomieniu”.
Tamás

28
Problem z „sessionStorage” polega na tym, że nie jest on zapisywany po otwarciu nowej karty, na przykład po kliknięciu łącza z wciśniętym klawiszem Ctrl. Potrzebuję lol hybrydowy localStorage / sessionStorage.
Edwin Stoteler

3
@EdwinStoteler Me też. Jestem trochę zdezorientowany, co myśleli, kiedy zaprojektowali to w ten sposób. Naprawdę potrzebuję dostępu w zasadzie tylko do pamięci przeglądarki, która jest zniszczona po zamknięciu przeglądarki. Chcę przechowywać poufne informacje w sposób umożliwiający dostęp do nich w całej domenie, ale nie chcę, aby te informacje trafiały na dyski twarde.
BT

19

Spróbuj użyć

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

Mam nadzieję, że to Ci odpowiada


2
czy chcesz wyczyścić cały localStorage? jeśli tak, po prostu użyjlocalStorage.clear();
Rafael Marques

było jasne, co chcę w pytaniu - tylko klawisz usuń + wartość
Yosef

12
Spowoduje to wyczyszczenie całego lokalnego magazynu. złe rozwiązanie!
Emmy

12

Istnieje bardzo szczególny przypadek użycia, w którym jakakolwiek sugestia użycia sessionStorage zamiast localStorage tak naprawdę nie pomaga. Przypadek użycia byłby czymś tak prostym, jak przechowywanie czegoś, gdy masz przynajmniej jedną otwartą kartę, ale unieważnij to, jeśli zamkniesz ostatnią pozostałą kartę. Jeśli potrzebujesz, aby twoje wartości były zapisywane między kartami i oknem, sessionStorage nie pomoże ci, chyba że komplikujesz swoje życie słuchaczom, tak jak próbowałem. W międzyczasie localStorage byłby do tego idealny, ale wykonuje to zadanie „zbyt dobrze”, ponieważ twoje dane będą tam czekać nawet po ponownym uruchomieniu przeglądarki. Skończyło się na użyciu niestandardowego kodu i logiki, która korzysta z obu.

Wolę wyjaśnić, niż podać kod. Najpierw zapisz to, czego potrzebujesz w localStorage, a następnie również w localStorage utwórz licznik, który będzie zawierał liczbę otwartych kart. Będzie to zwiększane za każdym razem, gdy strona się ładuje, i zmniejszane za każdym razem, gdy strona się rozładowuje. Tutaj możesz wybrać wydarzenia, które chcesz użyć, sugeruję „załaduj” i „rozładuj”. Podczas rozładowywania musisz wykonać zadania czyszczenia, które chcesz, gdy licznik osiągnie 0, co oznacza, że ​​zamykasz ostatnią kartę. Oto trudna część: nie znalazłem wiarygodnego i ogólnego sposobu na odróżnienie przeładowania strony lub nawigacji na stronie od zamknięcia karty. Jeśli więc przechowywane dane nie są czymś, co można odbudować po załadowaniu po sprawdzeniu, że jest to Twoja pierwsza karta, nie można go usunąć przy każdym odświeżeniu. Zamiast tego należy przechowywać flagę w sessionStorage przy każdym ładowaniu przed zwiększeniem licznika tabulatorów. Przed zapisaniem tej wartości możesz sprawdzić, czy ma ona już wartość, a jeśli nie, oznacza to, że ładujesz się do tej sesji po raz pierwszy, co oznacza, że ​​możesz wykonać czyszczenie przy ładowaniu, jeśli to wartość nie jest ustawiona, a licznik wynosi 0.


W odpowiedzi na pytanie „dlaczego nie użyć sessionStorage?” podejście, również z w3schools.com/html/html5_webstorage.asp : „window.sessionStorage - przechowuje dane dla jednej sesji (dane są tracone, gdy karta jest zamknięta)”. Odpowiedź jest właśnie taka. sessionStorage jest bezużyteczne, jeśli chcesz czegoś trwałego nawet w opisanym przeze mnie przypadku użycia.
Solthun,

3
Myślę, że najlepszą implementacją do tego jest usługa browserWatcher, która w zasadzie uruchamia zdarzenia, których inne komponenty mogą słuchać (tj. Otwieranie przeglądarki, zamykanie przeglądarki, ładowanie przeglądarki, rozładowywanie przeglądarki itp. I ukrywanie w niej wszystkich szczegółów implementacji Każdy komponent może zdecydować, które zdarzenia musi obsłużyć, aby wykonać swoją pracę. Moje jedyne pytanie dotyczyłoby tego, co się stanie, jeśli nastąpi odcięcie zasilania maszyny lub czegoś, to właściwości te pozostaną w localStorage przy następnym otwarciu przeglądarki, czy nie ?
pQuestions123

11

użyj sessionStorage

Obiekt sessionStorage jest równy obiektowi localStorage, z wyjątkiem tego, że przechowuje dane tylko dla jednej sesji. Dane są usuwane, gdy użytkownik zamyka okno przeglądarki.

Poniższy przykład zlicza liczbę kliknięć przycisku przez użytkownika w bieżącej sesji:

Przykład

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
Dane są usuwane na karcie przeglądarki zamknij.
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
Odpowiadając na stare pytanie, twoja odpowiedź byłaby znacznie bardziej przydatna dla innych użytkowników StackOverflow, gdybyś podał kontekst wyjaśniający, w jaki sposób twoja odpowiedź pomaga, szczególnie w przypadku pytania, które ma już zaakceptowaną odpowiedź. Zobacz: Jak napisać dobrą odpowiedź .
Tân

Wydaje mi się wystarczająco jasne
Giorgio Tempesta

4

Chociaż niektórzy użytkownicy już odpowiedzieli na to pytanie, podam przykład ustawień aplikacji, aby rozwiązać ten problem.

Miałem ten sam problem. Korzystam z modułu https://github.com/grevory/angular-local-storage w mojej aplikacji angularjs. Jeśli skonfigurujesz aplikację w następujący sposób, zapisze ona zmienną w pamięci sesji zamiast w pamięci lokalnej. Dlatego jeśli zamkniesz przeglądarkę lub zamkniesz kartę, pamięć sesji zostanie automatycznie usunięta. Nie musisz nic robić.

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

Mam nadzieję, że to pomoże.


4

Istnieje pięć metod do wyboru:

  • setItem (): Dodaj klucz i wartość do localStorage
  • getItem (): pobierz wartość według klucza z localStorage
  • removeItem (): Usuń element według klucza z localStorage
  • clear (): Wyczyść wszystkie localStorage
  • key (): Przeszedł numer, aby pobrać n-ty klucz localStorage

Możesz użyć clear (), ta metoda po wywołaniu usuwa całą pamięć wszystkich rekordów dla tej domeny. Nie otrzymuje żadnych parametrów.

window.localStorage.clear();

3

Oto prosty test, aby sprawdzić, czy masz obsługę przeglądarki podczas pracy z pamięcią lokalną:

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

Działa dla mnie zgodnie z oczekiwaniami (używam Google Chrome). Zaadaptowano z: http://www.w3schools.com/html/html5_webstorage.asp .


3

Nie sądzę, aby przedstawione tutaj rozwiązanie było w 100% poprawne, ponieważ zdarzenie window.onbeforeunload jest wywoływane nie tylko wtedy, gdy przeglądarka / karta jest zamknięta (CO JEST WYMAGANE), ale także w przypadku wszystkich innych kilku zdarzeń. (KTÓRE MOGĄ NIE BYĆ WYMAGANE)

Zobacz ten link, aby uzyskać więcej informacji na temat listy zdarzeń, które mogą uruchomić Window.onbeforeunload: -

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


Być może masz rację, ale mimo to opublikowałeś komentarz, a nie odpowiedź.
nnnnnn


3

Po przeanalizowaniu tego pytania 6 lat po zadaniu okazało się, że wciąż nie ma wystarczającej odpowiedzi na to pytanie; które powinny osiągnąć wszystkie następujące warunki:

  • Wyczyść pamięć lokalną po zamknięciu przeglądarki (lub wszystkich kart domeny)
  • Zachowaj pamięć lokalną na różnych kartach, jeśli przynajmniej jedna karta pozostanie aktywna
  • Zachowaj pamięć lokalną podczas ponownego ładowania pojedynczej karty

Wykonaj ten fragment javascript na początku każdego ładowania strony, aby osiągnąć powyższe:

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

Edycja: Podstawowa idea tutaj jest następująca:

  1. Rozpoczynając od zera, do pamięci sesji przypisany jest losowy identyfikator w kluczu o nazwie tabid
  2. Pamięć lokalna jest następnie ustawiana za pomocą klucza tabszawierającego obiekt zawierający klucztabid jest ustawiony na 1.
  3. Po zwolnieniu karty pamięć lokalna tabsjest aktualizowana do obiektu zawierającegotabid wartość 0.
  4. Jeśli karta zostanie ponownie załadowana, najpierw zostanie rozładowana i wznowiona. Ponieważ tabidistnieje klucz pamięci sesji , podobnie jak lokalny tabsklucz pamięci z podkluczemtabid pamięci lokalnej nie jest czyszczony.
  5. Gdy przeglądarka zostanie zwolniona, cała pamięć sesji zostanie wyczyszczona. Po wznowieniu tabidnie będzie już miejsca na sesję i tabidzostanie wygenerowane nowe . Ponieważ pamięć lokalna nie ma podklucza do tego tabidani żadnego innegotabid (wszystkie sesje zostały zamknięte), została wyczyszczona.
  6. Po utworzeniu nowo utworzonej karty nowa tabidpamięć jest generowana w pamięci sesji, ale ponieważ istnieje co najmniej jedna tabs[ tabid], pamięć lokalna nie jest czyszczona

1
Jeśli jednak window.onbeforeunloadnastąpi awaria przeglądarki, nie zostanie ona wywołana, a tabs[tabid]pamięć lokalna nie zostanie ustawiona na 0 => pamięć lokalna nigdy nie zostanie wyczyszczona. Myślę, że w takim przypadku bardziej odpowiedni byłby organ nadzorczy, zamiast pisać 1 przy ładowaniu tabulatorów, powinieneś zapisać aktualny znacznik czasu. Następnie w części zmniejszającej powinieneś potwierdzić opóźnienie, ponieważ ten znacznik czasu nie jest zbyt duży lub zastąpić go 0, jeśli tak jest. W ten sposób nie zależysz od faktycznego wezwania onbeforeunload. Karta musi tylko od czasu do czasu resetować watchdoga, aby zachować lokalną pamięć.
xryl669,

1

To stare pytanie, ale wydaje się, że żadna z powyższych odpowiedzi nie jest idealna.

W przypadku, gdy chcesz uwierzytelniania sklepu lub poufnych informacji, które są zniszczeniu dopiero wtedy, gdy przeglądarka jest zamknięta, na której można polegać sessionStorageilocalStorage do wiadomości cross-tab podjęcia.

Zasadniczo chodzi o:

  1. Bootstrap z żadnej poprzedniej karty nie został otwarty, więc zarówno twój, jak localStoragei sessionStoragepusty są (jeśli nie, możesz wyczyścić localStorage). Musisz zarejestrować odbiornik zdarzenia wiadomości wlocalStorage .
  2. Użytkownik uwierzytelnia / tworzy poufne informacje na tej karcie (lub dowolnej innej karcie otwartej w domenie).
  3. Aktualizujesz, sessionStorageaby przechowywać poufne informacje, i używasz localStoragedo przechowywania tych informacji, a następnie je usuwasz (nie przejmujesz się czasem, ponieważ zdarzenie było w kolejce, gdy dane się zmieniły). Każda inna zakładka otwarta w tym czasie zostanie wywołana ponownie w przypadku zdarzenia wiadomości i zaktualizuje ichsessionStorage o poufne informacje.
  4. Jeśli użytkownik otworzy nową kartę w domenie, sessionStoragebędzie ona pusta. Kod będzie musiał ustawić klucz w localStorage(na przykład:) req. Każda (wszystkie) inna karta zostanie wywołana z powrotem w zdarzeniu wiadomości, zobacz ten klucz i może odpowiedzieć poufnymi informacjami z ich sessionStorage(jak w 3), jeśli takie mają.

Zauważ, że ten schemat nie zależy od window.onbeforeunloadwydarzenia, które jest delikatne (ponieważ przeglądarkę można zamknąć / zawiesić bez uruchamiania tych zdarzeń). Czas przechowywania poufnych informacji wlocalStorage bardzo mały (ponieważ polegasz na wykrywaniu zmian trans przejęć w przypadku komunikatu między kartami), więc jest mało prawdopodobne, aby takie wrażliwe informacje wyciekły na dysk twardy użytkownika.

Oto demo tej koncepcji: http://jsfiddle.net/oypdwxz7/2/


Dziękuję za edycję xryl669, dobrze trafiłeś. Czy teraz, gdy o tym myślę, najlepiej byłoby użyć współdzielonego pracownika sieci? developer.mozilla.org/en-US/docs/Web/API/SharedWorker na wypadek, gdyby bieżąca obsługa przeglądarki nie stanowiła problemu
Hacktisch

Tak, możesz użyć SharedWorker lub BroadcastChannel (lub localStorage jak ten), chociaż dwa pierwsze nie są dostępne w Edge. Zasadniczo każda metoda działająca na różnych kartach, w różnych oknach będzie działać. Trudność polega na znalezieniu takiego, który działa wszędzie przy minimalnym wysiłku.
xryl669,

1

Nie ma takiego sposobu na wykrycie zamknięcia przeglądarki, więc prawdopodobnie nie możesz usunąć localStorage na zamknięciu przeglądarki, ale jest też inny sposób radzenia sobie z rzeczami, których możesz użyć sessionCookies, ponieważ zniszczą się po zamknięciu przeglądarki. Jest to zaimplementowane w moim projekcie.


0

Możesz po prostu użyć sessionStorage. Ponieważ sessionStorage pozwala wyczyścić wszystkie wartości klucza, gdy okno przeglądarki zostanie zamknięte.

Zobacz tam: SessionStorage- MDN


-5

możesz spróbować użyć następującego kodu, aby usunąć pamięć lokalną:

delete localStorage.myPageDataArr;

29
To nie jest właściwy sposób usuwania klucza localStorage. Powinieneś użyć, localStorage.removeItem(key);aby usunąć klucz.
MT.

1
Powinien użyć localStorage.removeItem (key); nie słowo kluczowe usuwania.
Rob Evans,

@MT. Dlaczego nie używać delete? Próbowałem i to działa. Czy jest jakiś efekt uboczny lub coś, czego nie powinniśmy używać delete? Dziękuję Ci.
user1995781

2
@ user1995781 używanie deletenie jest najlepszą praktyką wlocalStorage
justmyfreak

1
@justmyfreak To nie jest odpowiedź
alvitawa
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.