Как удалить элемент 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
Если вы хотите очистить локальное хранилище после закрытия браузера, я бы поставил под сомнение ваши причины его использования.
Данхаммзз
16
Вы можете иметь как локальные, так и сессионные объекты хранения - я бы использовал sessionStorage для значений сессии. Кстати, установка значения в undefined не удаляет его и не удаляет его из localStorage, а просто устанавливает его значение в undefined.
Кеннебек
2
@kennebec - хотя установка на undefinedперезапишет ранее сохраненный элемент. Но да, использование .removeItem()более уместно.
nnnnnn
2
просто используйте sessionStorage вместо localStorage
Alberto Acuña
2
Используйте, localStorage.clear(); если вы хотите очистить все хранилище.
Черная мамба

Ответы:

802

должно быть сделано так, а не с оператором удаления:

localStorage.removeItem(key);
Йосеф
источник
1
Почему мы не можем использовать оператор удаления? Из моих тестов кажется, что delete localStorage.keyработает так же хорошо, как и localStorage.removeItem(key). Мне кажется более понятным использовать delete, когда я устанавливаю свои переменные как, localStorage.key = 1а не localStorage.setItem('key', 1).
Ост
6
Если это работает, вы можете использовать его технически. Но, учитывая, что removeItem предоставляется как функция-член, кажется логичным использовать его, а не сталкиваться с потенциально неопределенным поведением с использованием отдельного оператора.
кунгфу
@kungphu имейте в виду, что всегда можно (случайно) сделать localStorage.removeItem = null;, создавая localStorage.removeItem(key);потенциально плохую идею.
Skeggse
31
Я не понимаю, насколько это разумное обстоятельство для планирования. Тот факт, что язык позволяет людям совершать деструктивные действия, не означает, что вы должны использовать нестандартные способы использования библиотек для защиты от неправильного использования языка. Если вы или ваши коллеги-разработчики не понимаете разницу между вызовом и назначением, у вас гораздо большие проблемы, чем то, как лучше всего удалить элементы из localStorage.
кунгфу
3
@skeggse, именно поэтому писать плохую идею - localStorage.key = 1во-первых, чтобы избежать несчастных случаев такого рода
Дживан
114

Использовать с windowглобальным ключевым словом: -

 window.localStorage.removeItem('keyName');
Vineet
источник
6
зачем использовать окно Object? просто localStorage.removeItem(key)отлично работает
Пардип Джайн
3
проверьте эту ссылку stackoverflow.com/questions/5319878/…
vineet
Это решение действительно работает для IE 11? Пожалуйста, предложите. У меня эта проблема в коде угловых 5.
Каран
95

Вы можете использовать beforeunloadсобытие в JavaScript.

Используя ванильный JavaScript, вы можете сделать что-то вроде:

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

Это удалит ключ до закрытия окна / вкладки браузера и предложит вам подтвердить действие закрытия окна / вкладки. Я надеюсь, что это решит вашу проблему.

ПРИМЕЧАНИЕ. onbeforeunloadМетод должен возвращать строку.

Гора
источник
Это было действительно полезно. Было бы неплохо принять ответ (даже после всего этого времени).
Ричард Морган
8
@dhsto VanillaJS - простой JavaScript :) Посмотрите здесь: Что такое VanillaJS? ,
Бхарат Хатри
1
Одна проблема заключается в том, что это вызывается, даже если вы переходите на одну и ту же страницу, а не только когда вкладка закрыта, что может не соответствовать тому, что предназначено. Примечание: возврат undefined из onbeforeunload отключит сообщение, отображаемое при выгрузке.
Стэн Бонди
Что произойдет, если пользователь захочет остаться на странице, а вы уже удалите локальное хранилище? Также решение не работает на Chrome и IE11
oracleruiz
Почему бы тогда не использовать sessionStorage?
Сачин Прасад
94

Вместо этого вы должны использовать sessionStorage, если вы хотите, чтобы ключ был удален при закрытии браузера.

Graou13
источник
3
Это лучший ответ; sessionStorageявляется средством от того, что описывает спрашивающий.
Бенни
8
+1 за упоминание sessionStorage, но черновик редактора W3C гласит: «Время существования контекста просмотра может быть не связано со временем жизни самого процесса пользовательского агента, поскольку пользовательский агент может поддерживать возобновление сеансов после перезапуска».
Тамас
28
Проблема с 'sessionStorage' заключается в том, что он не сохраняется при открытии новой вкладки, например, при нажатии Ctrl по ссылке. Мне нужен гибрид LocalStorage / sessionStorage LOL.
Эдвин Стотелер
3
@ EdwinStoteler Я тоже. Я немного запутался в том, что они думали, когда разрабатывали это таким образом. Мне действительно нужен доступ к хранилищу браузера только в памяти, которое уничтожается при закрытии браузера. Я хочу хранить конфиденциальную информацию таким образом, чтобы к ней можно было получить доступ по всему домену, но я не хочу, чтобы эта информация попала на любые жесткие диски.
BT
19

Попробуйте использовать

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

Надеюсь, что это работает для вас

Рафаэль Маркиз
источник
2
Вы хотите очистить весь localStorage? если так, просто используйтеlocalStorage.clear();
Рафаэль Маркиз
Это было ясно, что я хочу в вопросе - только ключ удалить + значение
Йосеф
12
Это очистит все местное хранилище. плохое решение!
Эмми
12

Существует очень специфический вариант использования, в котором любое предложение использовать sessionStorage вместо localStorage действительно не помогает. Вариант использования будет таким же простым, как сохранение чего-либо, пока у вас есть хотя бы одна открытая вкладка, но аннулируйте его, если закроете последнюю оставшуюся вкладку. Если вам нужно сохранить свои значения в кросс-таблице и окне, sessionStorage не поможет вам, если вы не усложните свою жизнь со слушателями, как я пытался. В то же время localStorage идеально подходит для этого, но он выполняет свою работу «слишком хорошо», так как ваши данные будут ждать там даже после перезапуска браузера. В итоге я использовал собственный код и логику, которые используют оба преимущества.

Я лучше объясню, потом дам код. Сначала сохраните то, что вам нужно, в localStorage, затем также в localStorage создайте счетчик, который будет содержать количество открытых вами вкладок. Это будет увеличиваться при каждой загрузке страницы и уменьшаться при каждой ее загрузке. Вы можете выбрать здесь, какие события использовать, я бы предложил «загрузить» и «выгрузить». В то время, когда вы выгружаете, вам нужно выполнять задачи очистки, которые вы хотели бы выполнять, когда счетчик достигает 0, то есть вы закрываете последнюю вкладку. Здесь возникает сложная часть: я не нашел надежного и универсального способа определить разницу между перезагрузкой страницы или навигацией внутри страницы и закрытием вкладки. Поэтому, если данные, которые вы храните, не могут быть перестроены при загрузке после проверки того, что это ваша первая вкладка, тогда вы не можете удалить его при каждом обновлении. Вместо этого вам нужно хранить флаг в sessionStorage при каждой загрузке, прежде чем увеличивать счетчик вкладок. Перед сохранением этого значения вы можете проверить, есть ли у него значение, а если нет, это означает, что вы загружаетесь в этот сеанс впервые, то есть вы можете выполнить очистку при загрузке, если это значение не установлено, а счетчик равен 0.

Solthun
источник
Как ответ на вопрос "почему не используется sessionStorage?" подход, также с w3schools.com/html/html5_webstorage.asp : «window.sessionStorage - сохраняет данные за один сеанс (данные теряются при закрытии вкладки)». Так что ответ только на это. sessionStorage бесполезен, если вы хотите что-то постоянное даже в описанном выше случае использования.
Solthun
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.";
DilanG
источник
1
Данные удаляются на вкладке браузера.
Космонафт
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, если бы вы включили некоторый контекст для объяснения того, как ваш ответ помогает, особенно для вопроса, на который уже есть принятый ответ. Смотрите: Как мне написать хороший ответ .
Tân
Выглядит достаточно ясно для меня
Джорджио Темпеста
4

Хотя некоторые пользователи уже ответили на этот вопрос, я привожу пример настроек приложения для решения этой проблемы.

Я была такая же проблема. Я использую https://github.com/grevory/angular-local-storage модуль в моем приложении angularjs. Если вы настроите свое приложение следующим образом, оно сохранит переменную в хранилище сеансов вместо локального хранилища. Поэтому, если вы закроете браузер или закроете вкладку, хранилище сеанса будет автоматически удалено. Вам не нужно ничего делать.

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

Надеюсь, это поможет.

user1012513
источник
4

Есть пять методов на выбор:

  • setItem (): добавить ключ и значение в localStorage
  • getItem (): получить значение по ключу из localStorage
  • removeItem (): удалить элемент по ключу из localStorage
  • clear (): очистить все localStorage
  • key (): передал номер, чтобы получить n-й ключ localStorage

Вы можете использовать clear (), этот метод при вызове очищает все хранилище всех записей для этого домена. Он не получает никаких параметров.

window.localStorage.clear();
marcorchito8
источник
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 .

rdonatoiop
источник
3

Я не думаю, что представленное здесь решение на 100% правильно, потому что событие window.onbeforeunload вызывается не только тогда, когда браузер / вкладка закрыта (что требуется), но и для всех остальных нескольких событий. (КОТОРОЕ НЕ ТРЕБУЕТСЯ)

Смотрите эту ссылку для получения дополнительной информации о списке событий, которые могут вызвать window.onbeforeunload: -

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

miztaken
источник
Вы можете быть правы, но вы все равно оставляете комментарий, а не ответ.
nnnnnn
3

почему не используется sessionStorage?

«Объект sessionStorage равен объекту localStorage, за исключением того, что он хранит данные только для одного сеанса. Данные удаляются, когда пользователь закрывает окно браузера».

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

wjfinder77
источник
3

Посмотрев на этот вопрос через 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
  2. Локальное хранилище затем задается ключом, tabsсодержащим объект, для которого ключ tabidимеет значение 1.
  3. Когда вкладка выгружена, локальное хранилище tabsобновляется до объекта, содержащего tabidзначение 0.
  4. Если вкладка перезагружена, она сначала выгружается и возобновляется. Поскольку ключ хранилища сеансов tabidсуществует, и поэтому tabsключ локального хранилища с вложенным ключом tabidлокального хранилища не очищается.
  5. Когда браузер выгружен, все хранилище сеанса будет очищено. При возобновлении хранилища сеанса tabidбольше не существует, и tabidбудет сгенерировано новое . Поскольку локальное хранилище не имеет ни подключа tabidни этого , ни какого-либо другого tabid(все сеансы были закрыты), оно очищается.
  6. После создания новой вкладки tabidв хранилище сеанса генерируется новое , но поскольку существует хотя бы один tabs[ tabid], локальное хранилище не очищается
Hacktisch
источник
1
Однако, если происходит сбой браузера, window.onbeforeunloadне будет вызвано и tabs[tabid]локальное хранилище не будет установлено равным 0 =>, локальное хранилище больше никогда не будет очищено. Я думаю, что сторожевой таймер был бы более уместным в этом случае, вместо записи 1 при загрузке вкладки, вы должны написать текущую метку времени. Затем в части сокращения вы должны установить задержку, поскольку эта временная метка не слишком велика, или заменить ее на 0, если она есть. Таким образом, вы не зависите от фактического вызова onbeforeunload. Вкладке просто необходимо время от времени переустанавливать сторожевой таймер для поддержания существования локального хранилища.
xryl669
2

Вы можете просто использовать sessionStorage. Потому что sessionStorage позволяет очистить все значения ключа, когда окно браузера будет закрыто.

Смотрите там: SessionStorage - MDN

Мошиур Рахман
источник
1

Это старый вопрос, но, похоже, ни один из приведенных выше ответов не идеален.

В случае, если вы хотите сохранить аутентификацию или любую конфиденциальную информацию, которая уничтожается только при закрытом браузере, вы можете положиться sessionStorageиlocalStorage для закладок креста передачи сообщений.

По сути, идея заключается в следующем:

  1. Вы загружаете из предыдущей открытой вкладки, таким образом, и ваша, localStorageи sessionStorageпустая (если нет, вы можете очистить localStorage). Вам нужно будет зарегистрировать прослушиватель сообщений наlocalStorage .
  2. Пользователь аутентифицирует / создает конфиденциальную информацию на этой вкладке (или любой другой вкладке, открытой на вашем домене).
  3. Вы обновляете, sessionStorageчтобы сохранить конфиденциальную информацию, и используете ее localStorageдля хранения этой информации, а затем удаляете ее (здесь вам не нужно время, так как событие было поставлено в очередь при изменении данных). Любая другая вкладка, открытая в это время, будет отозвана по событию сообщения и обновит их sessionStorageконфиденциальной информацией.
  4. Если пользователь откроет новую вкладку на вашем домене, она sessionStorageбудет пустой. Код должен будет установить ключ в localStorage(например:) req. Любая (все) другая вкладка будет вызвана обратно в событии сообщения, увидит этот ключ и может ответить секретной информацией из своих sessionStorage(как в 3), если они есть.

Обратите внимание, что эта схема не зависит от window.onbeforeunloadсобытия, которое является хрупким (так как браузер может быть закрыт / сбой без запуска этих событий). Кроме того, время, когда конфиденциальная информация хранится наlocalStorage очень мало (поскольку вы полагаетесь на обнаружение изменения переходных процессов при событии сообщения с перекрестными табуляциями), поэтому маловероятно, что такая конфиденциальная информация попадет на жесткий диск пользователя.

Вот демонстрация этой концепции: http://jsfiddle.net/oypdwxz7/2/

xryl669
источник
Спасибо за правку xryl669, вы сделали хороший вывод. Когда я сейчас думаю об этом, было бы лучше всего использовать веб-работника с общим доступом? developer.mozilla.org/en-US/docs/Web/API/SharedWorker на случай, если текущая поддержка браузера не является проблемой
Hacktisch
Да, вы можете использовать SharedWorker или BroadcastChannel (или подобный localStorage), хотя первые два недоступны в Edge. В принципе, любой метод, который является кросс-таблицей, кросс-окно, будет работать. Трудность заключается в том, чтобы найти тот, который работает везде с минимумом хлопот.
xryl669
1

Нет такого способа определения закрытия браузера, поэтому, вероятно, вы не можете удалить localStorage при закрытии браузера, но есть другой способ обработки вещей, которые вы можете использовать с помощью sessionCookies, так как он уничтожит после закрытия браузера. Это я реализовал в своем проекте.

Амит Двиведи
источник
-5

Вы можете попробовать следующий код для удаления локального хранилища:

delete localStorage.myPageDataArr;
aztechy
источник
29
Это неправильный способ удаления ключа localStorage. Вы должны использовать, localStorage.removeItem(key);чтобы удалить ключ.
MT.
1
Следует использовать localStorage.removeItem (ключ); не ключевое слово delete.
Роб Эванс
@MT. Почему не пользуетесь delete? Я пытался, и это работает. Есть ли побочный эффект или что-то, что мы не должны использовать delete? Спасибо.
user1995781
2
@ user1995781 использование delete- не лучшая практикаlocalStorage
justmyfreak
1
@justmyfreak Это не ответ
alvitawa