Сесія браузера частка між вкладками?


151

У мене на сайті є деякі значення, які я хочу очистити, коли браузер закритий. Я вирішив sessionStorageзберігати ці значення. Коли вкладка закрита, вони дійсно очищаються та зберігаються, якщо користувач натискає f5; Але якщо користувач відкриє якесь посилання на іншій вкладці, ці значення недоступні.

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

Випадок використання: поставте значення в деякий сховище, збережіть це значення доступним на всіх вкладках браузера та очистіть його, якщо всі вкладки закриті.

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

9
Мені дивно, що це закрили як дублікат. Висунення для повторного відкриття. Інша тема - про те, "як спілкуватися між декількома вкладками", яка звучить по-різному, а також відрізняється, коли я починаю читати цю іншу тему.
KajMagnus

Можливо використовувати файли cookie? які поводяться так за замовчуванням? (Але на самому справі - для отримання і установки дії , які вони зажадають подальшої реалізації) developer.mozilla.org/en-US/docs/Web/API/Document/cookie
lingar

Відповіді:


133

Ви можете використовувати 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, тобто9

Цей метод "повинен працювати в IE8", але я не міг перевірити його, оскільки мій IE виходив з ладу кожен раз, коли я відкривав вкладку .... будь-яку вкладку ... на будь-якому веб-сайті. (добре ol IE) PS: вам, очевидно, потрібно буде включити прокладку JSON, якщо ви хочете також підтримати IE8. :)

Заслуга цієї повної статті: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/


2
Наскільки надійне це рішення? Оскільки це основа подій, чи є шанс пропустити подію?
vivek241

2
На основі відповідей тут я створив бібліотеку через localStorage та sessionStorage, щоб спростити це. Отже, ви просто викликаєте storageManager.saveSyncedSessionData ("дані", "ключ"); або storageManager.savePermanentData ("дані", "ключ") тощо, залежно від того, що вам потрібно. Повний код тут: ebenmonney.com/blog/…
adentum

@ vivek241 Рішення для мене чудово працювало, коли розмір файлу JS був меншим, а "скрипт рішення", наведений вище, завантажується як перший скрипт на сторінку. Коли мій JS-файл зростав занадто великим, скажімо, 1000 або більше рядків, він раптово припинив роботу, а також видалив мої файли cookie та конкретні дані LocalStorage. Я не впевнений, що це надійне або крос-браузерне рішення, на яке можна покластися. Отже, переписав усю логіку, щоб вирішити проблему лише cookie.
веббловер

4
Чи не відбудеться подія на всіх раніше відкритих вкладках?
Dtipson

3
Схоже, BroadcastChannelзараз це гарний інструмент для цього. developers.google.com/web/updates/2016/09/broadcastchannel
alexbea

71

Використовувати sessionStorageдля цього неможливо.

З Документів MDN

Відкриття сторінки в новій вкладці або вікні призведе до початку нового сеансу.

Це означає, що ви не можете ділитися між вкладками, для цього вам слід скористатися localStorage


8
Гаразд, я це отримав, але як я можу очистити localStorage, коли всі вкладки браузера закриті?
Володимир Гордієнко

Ви можете змінити файл cookie документів, щоб path='/'змусити його очищати, коли вікно браузера закриється. Але щодо вкладок, я зараз не маю уявлення.
Генрік Андерссон

ок, я буду копати глибше і повідомляти, якщо я знайшов рішення, нехай зараз подумає, що неможливо))
Володимир Гордієнко

5
@Anmol так, але я вже не можу надати будь-який код, це було дуже давно. це некрасиве рішення, але воно працює на мене чудово. Ключовим моментом є збереження вкладених лічильників вкладених файлів у локальному сховищі та збільшення їх на завантаженні сторінки, але зменшення на завантаження сторінки. Отже, коли сторінка розвантажується та вкладені вкладкиOpen == 1 остання вкладка, і ми можемо очистити всі речі. Були деякі незначні речі, з якими мені потрібно було впоратися, але не можу пригадати, що саме. Сподіваюся, це допоможе тобі!
Володимир Гордієнко

1
@VladimirGordienko що робити, якщо подія завантаження, яка видаляє localStorageдані, станеться тому, що хтось переходить на інший домен, на одній вкладці. Мені здається, це неправильно видалить localStorageдані - вкладка не закриється, і якщо людина перейде назад, він / він захоче отримати дані знову, правильно. У всякому разі, це цікавий підхід, не думав про це: -)
KajMagnus

9
  1. Ви можете просто використовувати localStorageта запам'ятати дату, в яку вона була створена вперше session cookie. Коли localStorage"сеанс" старший за значення файлу cookie, ви можете очиститиlocalStorage

    Мінуси цього полягають у тому, що хтось все ще може читати дані після закриття браузера, тому це не є гарним рішенням, якщо ваші дані приватні та конфіденційні.

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


9

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

У цьому посиланні є хороша jsfiddle, щоб перевірити її. sessionStorage у новому вікні не порожній, коли переходить посилання з target = "_ blank"


0

Моє рішення не мати sessionStorage для передачі через вкладки - створити localProfile і відбити цю змінну. Якщо ця змінна встановлена, але мій змінний sessionStorage не вдасться і реініціалізувати їх. Коли користувач виходить із вікна, він закривається, знищуйте цю змінну localStorage


-14

Ось рішення, щоб запобігти зсуву сеансу між вкладками браузера для програми java. Це буде працювати для IE (JSP / Servlet)

  1. На своїй першій сторінці JSP завантажте сервлет (виклик ajex), щоб встановити "window.title" та трекер подій у сеансі (просто ціла змінна, яку слід встановити як 0 вперше)
  2. Переконайтеся, що жодна з інших сторінок не встановила window.title
  3. Всі сторінки (включаючи першу сторінку) додають сценарій Java для перевірки заголовка вікна, коли завантаження сторінки завершено. якщо заголовок не знайдено, закрийте поточну сторінку / вкладку (обов'язково скасуйте функцію "window.unload", коли це відбувається)
  4. Встановіть сторінку window.onunload подія java script (для всіх сторінок) для захоплення події оновлення сторінки, якщо сторінка оновлена, зателефонуйте на сервлет, щоб скинути трекер подій.

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

3
Це питання щодо javascript, воно не має нічого спільного з javascript.
victorpacheco3107

Це питання детальніше про sessionStorage та localStorage
RR1112
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.