браузер sessionStorage. поделить между вкладками?

У меня есть некоторые значения на моем сайте, которые я хочу очистить при закрытии браузера. Я выбрал sessionStorage для хранения этих значений. Когда вкладка закрыта, они действительно очищаются и сохраняются, если пользователь нажимает f5; Но если пользователь открывает ссылку на другой вкладке, эти значения недоступны.

Как я могу поделиться sessionStorage значениями между всеми вкладками браузера с моим приложением?

Вариант использования: поместите значение в какое-либо хранилище, сохраните это значение доступным на всех вкладках браузера и очистите его, если все вкладки закрыты.

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}

person Vladimir Gordienko    schedule 02.12.2013    source источник
comment
Мне странно, что это закрылось как дубликат. Выдвижение на открытие. Другая тема - о том, как общаться между несколькими вкладками, что звучит по-разному, а также отличается, когда я начинаю читать эту другую тему.   -  person KajMagnus    schedule 22.02.2019
comment
Можно ли использовать куки? которые так себя ведут по умолчанию? (но действительно - для действий get и set они потребуют дальнейшей реализации) developer.mozilla.org/en-US/docs/Web/API/Document/cookie   -  person lingar    schedule 13.05.2020
comment
Похоже, что в какой-то момент sessionStorage синхронизировался между вкладками: stackoverflow.com/questions/19867599/   -  person Devin Rhode    schedule 20.05.2021
comment
Если вы находитесь в этой теме, вы также можете в какой-то момент задаться вопросом, каковы были исходные варианты использования sessionStorage? См .: stackoverflow.com/questions/8498357/   -  person Devin Rhode    schedule 20.05.2021


Ответы (7)


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

Этот код должен присутствовать на ВСЕХ вкладках. Он должен выполняться раньше других ваших скриптов.

// transfers sessionStorage from one tab to another
var sessionStorage_transfer = function(event) {
  if(!event) { event = window.event; } // ie suq
  if(!event.newValue) return;          // do nothing if no value to work with
  if (event.key == 'getSessionStorage') {
    // another tab asked for the sessionStorage -> send it
    localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
    // the other tab should now have it, so we're done with it.
    localStorage.removeItem('sessionStorage'); // <- could do short timeout as well.
  } else if (event.key == 'sessionStorage' && !sessionStorage.length) {
    // another tab sent data <- get it
    var data = JSON.parse(event.newValue);
    for (var key in data) {
      sessionStorage.setItem(key, data[key]);
    }
  }
};

// listen for changes to localStorage
if(window.addEventListener) {
  window.addEventListener("storage", sessionStorage_transfer, false);
} else {
  window.attachEvent("onstorage", sessionStorage_transfer);
};


// Ask other tabs for session storage (this is ONLY to trigger event)
if (!sessionStorage.length) {
  localStorage.setItem('getSessionStorage', 'foobar');
  localStorage.removeItem('getSessionStorage', 'foobar');
};

Я тестировал это в chrome, ff, safari, т.е. 11, т.е. 10, ie9

Этот метод «должен работать в IE8», но я не смог его протестировать, так как мой IE вылетал каждый раз, когда я открывал вкладку ... любую вкладку ... на любом веб-сайте. (старый добрый IE) PS: вам, очевидно, потребуется включить прокладку JSON, если вы также хотите поддерживать IE8. :)

Благодарим эту полную статью: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/

person nawlbergs    schedule 24.09.2015
comment
Насколько надежно это решение? Поскольку это событие основано на событиях, есть ли шанс пропустить событие? - person vivek241; 27.10.2015
comment
Основываясь на ответах здесь, я создал библиотеку через localStorage и sessionStorage, чтобы упростить это. Итак, теперь вы просто вызываете storageManager.saveSyncedSessionData ('data', 'key'); или storageManager.savePermanentData ('data', 'key'); и т. д. в зависимости от того, что вам нужно. Полный код находится здесь: ebenmonney.com/blog/ - person adentum; 14.12.2016
comment
@ vivek241 Решение отлично работало для меня, когда размер файла JS был меньше, а сценарий решения, указанный выше, загружается как первый сценарий на странице. Когда мой JS-файл стал слишком большим, скажем, на 1000 или более строк, он внезапно перестал работать и удалил мои файлы cookie и определенные данные localStorage. Я не уверен, что это надежное или кроссбраузерное решение, на которое можно положиться. Итак, переписал всю логику, чтобы решить проблему только с cookie. - person webblover; 18.01.2017
comment
Я подтверждаю, что этот скрипт (и библиотека) не работают, если вы используете их со сложным кодом javascript. Он не показывает никаких ошибок, но он не будет работать на новой вкладке, но он будет работать, если вы обновите эту новую вкладку. Я предполагаю, что это должно быть связано с асинхронным способом javascript, если ваш код можно реорганизовать, чтобы дождаться завершения работы хранилища (settimeout, Promise и т. Д.), Это может сработать. - person Persk; 10.02.2017
comment
Не будет ли событие запускаться на всех ранее открытых вкладках? - person Dtipson; 05.06.2017
comment
Этот пример не работает в IE 11 и Edge, не могли бы вы дать решение для этого. - person Nithinkumar CN; 17.09.2019
comment
FWIW, похоже, это больше не работает (добро пожаловать, из будущего ????). sessionStorage только запускает событие «хранилище» между кадрами внутри вкладки, поэтому этот (очень умный) процесс больше не будет работать для отслеживания изменений sessionStorage на вкладках. - person alexbea; 02.03.2020
comment
Похоже, BroadcastChannel теперь хороший инструмент для этого. developers.google.com/web/updates/2016/09/broadcastchannel - person alexbea; 02.03.2020
comment
Разве это не плохое решение, поскольку все вкладки, которые отслеживают изменения в localStorage, могут читать ваш sessionStorage? В чем тогда весь смысл использования SessionStorage, если таким образом вы сделаете себя уязвимым? Вроде да, это работает, но в каком-то смысле вы просто используете localstorage вместо сеанса. - person Riddim; 28.03.2020
comment
Однако это решает проблему, когда вы начинаете открывать несколько вкладок, так как у меня три вкладки, все мои вкладки зависают. - person Cham; 02.04.2020
comment
Я думаю, что BroadcastChannel - лучший способ решить эту проблему. Есть также полифиллы для BroadcastChannel (которые, как правило, используют localStorage под капотом) - person Devin Rhode; 13.03.2021
comment
Я исследовал все полифилы для BroadcastChannel, и это кажется лучшим вариантом: github.com/pubkey/broadcast- канал - person Devin Rhode; 13.03.2021

Использование sessionStorage для этого невозможно.

Из Документов MDN

Открытие страницы в новой вкладке или окне приведет к запуску нового сеанса.

Это означает, что вы не можете делиться между вкладками, для этого вы должны использовать localStorage

person Henrik Andersson    schedule 02.12.2013
comment
Хорошо, я понял, но как я могу очистить localStorage, когда все вкладки браузера закрыты? - person Vladimir Gordienko; 02.12.2013
comment
Вы можете изменить файл cookie документов на path='/', заставив его очищаться при закрытии окна браузера. Но насчет вкладок я сейчас понятия не имею. - person Henrik Andersson; 02.12.2013
comment
ок, я буду копать глубже и сообщу, нашел ли я решение, давай подумать, что это невозможно)) - person Vladimir Gordienko; 02.12.2013
comment
@VladimirGordienko Вы нашли способ очистить localStorage, когда все вкладки браузера закрыты? - person Anmol Gupta; 16.03.2016
comment
@Anmol да, но я уже не могу предоставить код, это было давно. это уродливое решение, но оно отлично работает для меня. Ключевым моментом здесь является сохранение счетчика tabsOpened в локальном хранилище и увеличение его при загрузке страницы, но уменьшение при выгрузке страницы. Итак, когда страница выгружается и tabsOpen == 1, это последняя вкладка, и мы можем очистить все. Было несколько мелких вещей, с которыми мне нужно было справиться, но я не могу вспомнить, что именно. Надеюсь, это поможет Вам! - person Vladimir Gordienko; 16.03.2016
comment
@VladimirGordienko, у пользователей может быть открыта вкладка в другом домене. - person Md Toufiqul Islam; 02.10.2017
comment
Вам нужно будет очистить сеанс, когда сайт снова откроется, а не при закрытии ... если вы не используете onunload - person doublejosh; 29.11.2017
comment
@VladimirGordienko, что, если событие выгрузки, которое удаляет данные localStorage, происходит из-за того, что кто-то переходит в другой домен на той же вкладке. Мне кажется, это приведет к неправильному удалению localStorage данных - вкладка не закрылась, и если человек вернется назад, он / она захочет получить данные снова, верно. В любом случае, подход интересный, не думал об этом: -) - person KajMagnus; 22.02.2019
comment
Если вы щелкните правой кнопкой мыши вкладку в Chrome и выберите дубликат, sessionStorage фактически будет использоваться как исходной, так и дублированной вкладками. - person Wilt; 29.10.2020

На самом деле, глядя на другие области, если вы открываете с помощью _blank, он сохраняет sessionStorage, пока вы открываете вкладку, когда открыт родительский элемент:

По этой ссылке есть хороший jsfiddle для его тестирования. sessionStorage в новом окне isn ' t пусто при переходе по ссылке с target = _blank

person Dan Parker    schedule 23.03.2016
comment
Это работает в Chromium, но не в FF. - person Antony; 25.02.2021
comment
это не работает в Chrome с версии 89 - developer.chrome.com/blog/deps -rems-89 - Остановить клонирование sessionStorage для окон, открытых с помощью noopener - person michal.jakubeczy; 17.06.2021

  1. Вы можете просто использовать localStorage и запомнить дату его первого создания в session cookie. Когда сеанс localStorage старше, чем значение файла cookie, вы можете очистить localStorage

    Минус в том, что кто-то все еще может читать данные после закрытия браузера, поэтому это не лучшее решение, если ваши данные конфиденциальны и конфиденциальны.

  2. Вы можете сохранить свои данные в localStorage на пару секунд и добавить прослушиватель событий для storage события. Таким образом вы будете знать, когда какая-либо вкладка написала что-то в localStorage, и вы можете скопировать ее содержимое в sessionStorage, а затем просто очистить localStorage

person Adassko    schedule 02.12.2013

Моим решением проблемы с переносом sessionStorage на вкладки было создание localProfile и отключение этой переменной. Если эта переменная установлена, но мои переменные sessionStorage не повторяют их инициализацию. Когда пользователь выходит из системы, окно закрывается, уничтожьте эту переменную localStorage

person yardpenalty.com    schedule 24.08.2016
comment
Как уничтожить localStorage, когда пользователь закрывает вкладки - person stevebaros; 24.05.2021

Если у вас небольшой объем данных, вы можете использовать вместо sessionStorage a session cookie, который остается активным до тех пор, пока пользователь не закроет свой браузер или не очистит свои файлы cookie. И он также сохраняет свою ценность среди нескольких вкладок.

Код для установки куки

document.cookie = "cookiename=value; path=/";

Опуская expires, мы устанавливаем session cookie.

И вы получаете его так:

function getCookie(name) {
  var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
  if (match) return match[2];
}

var value = getCookie('cookiename');
person michal.jakubeczy    schedule 17.06.2021

Вот решение, позволяющее предотвратить разрыв сеанса между вкладками браузера для Java-приложения. Это будет работать для IE (JSP / Servlet)

  1. На вашей первой странице JSP событие onload вызывает сервлет (вызов ajex) для настройки "window.title" и средства отслеживания событий в сеансе (просто целочисленная переменная, которая будет установлена ​​как 0 в первый раз)
  2. Убедитесь, что ни на одной из других страниц не задано window.title.
  3. Все страницы (включая первую) добавляют java-скрипт для проверки заголовка окна после завершения загрузки страницы. если заголовок не найден, закройте текущую страницу / вкладку (обязательно отмените функцию "window.unload", когда это произойдет)
  4. Установите событие java-скрипта page window.onunload (для всех страниц) для захвата события обновления страницы, если страница была обновлена, вызовите сервлет для сброса средства отслеживания событий.

1) первая страница JS

BODY onload="javascript:initPageLoad()"

function initPageLoad() {
    var xmlhttp;

    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {                           var serverResponse = xmlhttp.responseText;
            top.document.title=serverResponse;
        }
    };
                xmlhttp.open("GET", 'data.do', true);
    xmlhttp.send();

}

2) общий JS для всех страниц

window.onunload = function() {
    var xmlhttp;
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {             
            var serverResponse = xmlhttp.responseText;              
        }
    };

    xmlhttp.open("GET", 'data.do?reset=true', true);
    xmlhttp.send();
}

var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
    init();
    clearInterval(readyStateCheckInterval);
}}, 10);
function init(){ 
  if(document.title==""){   
  window.onunload=function() {};
  window.open('', '_self', ''); window.close();
  }
 }

3) web.xml - отображение сервлета

<servlet-mapping>
<servlet-name>myAction</servlet-name>
<url-pattern>/data.do</url-pattern>     
</servlet-mapping>  
<servlet>
<servlet-name>myAction</servlet-name>
<servlet-class>xx.xxx.MyAction</servlet-class>
</servlet>

4) код сервлета

public class MyAction extends HttpServlet {
 public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    Integer sessionCount = (Integer) request.getSession().getAttribute(
            "sessionCount");
    PrintWriter out = response.getWriter();
    Boolean reset = Boolean.valueOf(request.getParameter("reset"));
    if (reset)
        sessionCount = new Integer(0);
    else {
        if (sessionCount == null || sessionCount == 0) {
            out.println("hello Title");
            sessionCount = new Integer(0);
        }
                          sessionCount++;
    }
    request.getSession().setAttribute("sessionCount", sessionCount);
    // Set standard HTTP/1.1 no-cache headers.
    response.setHeader("Cache-Control", "private, no-store, no-cache, must-                      revalidate");
    // Set standard HTTP/1.0 no-cache header.
    response.setHeader("Pragma", "no-cache");
} 
  }
person DTB    schedule 20.01.2014
comment
Этот вопрос касается javascript, он не имеет ничего общего с javascript. - person victorpacheco3107; 17.09.2016
comment
Это вопрос больше о sessionStorage и localStorage. - person RR1112; 11.11.2019