Browser sessionStorage. zwischen Registerkarten teilen?

149

Ich habe einige Werte auf meiner Website, die ich löschen möchte, wenn der Browser geschlossen wird. Ich habe mich entschieden sessionStorage, diese Werte zu speichern. Wenn die Registerkarte geschlossen ist, werden sie tatsächlich gelöscht und beibehalten, wenn der Benutzer f5 drückt. Wenn der Benutzer jedoch einen Link auf einer anderen Registerkarte öffnet, sind diese Werte nicht verfügbar.

Wie kann ich sessionStorageWerte zwischen allen Browser-Registerkarten mit meiner Anwendung teilen ?

Der Anwendungsfall: Legen Sie einen Wert in einen Speicher, lassen Sie diesen Wert auf allen Browser-Registerkarten zugänglich und löschen Sie ihn, wenn alle Registerkarten geschlossen sind.

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}
Vladimir Gordienko
quelle
9
Es ist komisch für mich, dass dies als Duplikat geschlossen wurde. Nominierung für die Wiedereröffnung. Das andere Thema handelt von "Wie kommuniziere ich zwischen mehreren Registerkarten?", Was sich anders anhört und auch anders ist, wenn ich anfange, dieses andere Thema zu lesen.
KajMagnus
Es ist möglich, Cookies zu verwenden? welche verhalten sich standardmäßig so? (aber in der Tat - um Maßnahmen zu ergreifen und
festzulegen,

Antworten:

132

Sie können localStorage und seinen eventListener "Speicher" verwenden, um sessionStorage-Daten von einer Registerkarte auf eine andere zu übertragen.

Dieser Code muss auf ALLEN Registerkarten vorhanden sein. Es sollte vor Ihren anderen Skripten ausgeführt werden.

// 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');
};

Ich habe dies in Chrom, ff, Safari, dh 11, dh 10, dh 9 getestet

Diese Methode "sollte in IE8 funktionieren", aber ich konnte sie nicht testen, da mein IE jedes Mal abstürzte, wenn ich einen Tab öffnete ... einen beliebigen Tab ... auf einer beliebigen Website. (guter alter IE) PS: Sie müssen natürlich einen JSON-Shim einbinden, wenn Sie auch IE8-Unterstützung wünschen. :) :)

Gutschrift geht zu diesem vollständigen Artikel: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/

Nawlbergs
quelle
2
Wie zuverlässig ist diese Lösung? Gibt es eine Möglichkeit, ein Ereignis zu verpassen, da es ereignisbasiert ist?
vivek241
2
Basierend auf den Antworten hier habe ich eine Bibliothek über localStorage und sessionStorage erstellt, um dies zu vereinfachen. Rufen Sie jetzt einfach storageManager.saveSyncedSessionData ('data', 'key') auf. oder storageManager.savePermanentData ('data', 'key'); usw., je nachdem, was Sie benötigen. Der vollständige Code ist hier: ebenmonney.com/blog/…
adentum
@ vivek241 Die Lösung hat bei mir hervorragend funktioniert, als die JS-Dateigröße kleiner war und "das oben angegebene Lösungsskript" als erstes Skript auf der Seite geladen wurde. Als meine JS-Datei zu groß wurde, z. B. 1000 oder mehr Zeilen, funktionierte sie plötzlich nicht mehr und entfernte auch meine Cookies und bestimmte localStorage-Daten. Ich bin nicht sicher, ob dies eine zuverlässige oder browserübergreifende Lösung ist, auf die man sich verlassen kann. Schreiben Sie also die gesamte Logik neu, um das Problem nur mit Cookies zu lösen.
Webblover
4
Würde das Ereignis nicht in allen zuvor geöffneten Registerkarten ausgelöst?
Dtipson
3
Es sieht so aus, als wäre BroadcastChanneles jetzt ein gutes Werkzeug dafür. developer.google.com/web/updates/2016/09/broadcastchannel
alexbea
71

Eine Verwendung sessionStoragehierfür ist nicht möglich.

Aus den MDN-Dokumenten

Wenn Sie eine Seite in einem neuen Tab oder Fenster öffnen, wird eine neue Sitzung gestartet.

Das bedeutet, dass Sie nicht zwischen Registerkarten teilen können, dafür sollten Sie verwenden localStorage

Henrik Andersson
quelle
8
Ok, ich habe es verstanden, aber wie kann ich localStorage löschen, wenn alle Browser-Registerkarten geschlossen sind?
Vladimir Gordienko
Sie können das Dokument-Cookie path='/'so ändern , dass es beim Schließen des Browserfensters gelöscht wird. Aber für Tabs habe ich momentan keine Ahnung.
Henrik Andersson
ok ich werde tiefer graben und dich wissen lassen, wenn ich eine Lösung gefunden habe, lass uns jetzt
überlegen,
5
@Anmol ja, aber ich kann noch keinen Code bereitstellen, es ist lange her. Das ist eine hässliche Lösung, aber sie funktioniert perfekt für mich. Der Schlüssel besteht darin, den TabsOpened-Zähler im lokalen Speicher zu belassen und ihn beim Laden der Seite zu erhöhen, beim Entladen der Seite jedoch zu verringern. Wenn also die Seite entladen und tabsOpen == 1 die letzte Registerkarte ist, können wir alle Inhalte löschen. Es gab einige kleinere Dinge, die ich erledigen musste, aber ich kann mich nicht genau erinnern, was. Hoffe es wird dir helfen!
Vladimir Gordienko
1
@VladimirGordienko Was passiert, wenn das Entladeereignis, das die localStorageDaten löscht, auftritt , weil jemand auf derselben Registerkarte zu einer anderen Domäne navigiert ? Mir scheint, dies löscht die localStorageDaten fälschlicherweise - die Registerkarte wurde nicht geschlossen, und wenn die Person zurück navigiert, möchte sie die Daten erneut, richtig. Wie auch immer, es ist ein interessanter Ansatz, daran habe ich nicht gedacht: -)
KajMagnus
9
  1. Sie können einfach localStoragedas Datum verwenden und sich daran erinnern, an dem es zum ersten Mal erstellt wurde session cookie. Wenn localStorage"Sitzung" älter als der Wert des Cookies ist, können Sie das löschenlocalStorage

    Dies hat den Nachteil, dass jemand die Daten nach dem Schließen des Browsers noch lesen kann. Daher ist dies keine gute Lösung, wenn Ihre Daten privat und vertraulich sind.

  2. Sie können Ihre Daten localStoragefür einige Sekunden speichern und einen Ereignis-Listener für ein storageEreignis hinzufügen . Auf diese Weise wissen Sie, wann eine der Registerkarten etwas in das geschrieben hat, localStorageund Sie können den Inhalt in das kopieren sessionStorageund dann einfach das löschenlocalStorage

Adassko
quelle
0

Meine Lösung, um sessionStorage nicht über Registerkarten übertragen zu können, bestand darin, ein localProfile zu erstellen und diese Variable zu entfernen. Wenn diese Variable festgelegt ist, meine sessionStorage-Variablen jedoch nicht vorhanden sind, werden sie erneut initialisiert. Wenn das Fenster zum Abmelden des Benutzers geschlossen wird, wird diese Variable localStorage zerstört

yardpenalty.com
quelle
-14

Hier ist eine Lösung, um das Scheren von Sitzungen zwischen Browser-Registerkarten für eine Java-Anwendung zu verhindern. Dies funktioniert für IE (JSP / Servlet)

  1. Auf Ihrer ersten JSP-Seite rufen Sie beim Laden eines Ereignisses ein Servlet (Ajex-Aufruf) auf, um eine "window.title" und einen Ereignis-Tracker in der Sitzung einzurichten (nur eine ganzzahlige Variable, die zum ersten Mal als 0 festgelegt wird).
  2. Stellen Sie sicher, dass auf keiner der anderen Seiten ein window.title festgelegt ist
  3. Alle Seiten (einschließlich der ersten Seite) fügen ein Java-Skript hinzu, um den Fenstertitel zu überprüfen, sobald das Laden der Seite abgeschlossen ist. Wenn der Titel nicht gefunden wird, schließen Sie die aktuelle Seite / Registerkarte (stellen Sie sicher, dass die Funktion "window.unload" in diesem Fall rückgängig gemacht wird).
  4. Legen Sie das Java-Skriptereignis page window.onunload fest (für alle Seiten), um das Seitenaktualisierungsereignis zu erfassen. Wenn eine Seite aktualisiert wurde, rufen Sie das Servlet auf, um den Ereignistracker zurückzusetzen.

1) erste Seite 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) gemeinsames JS für alle Seiten

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-Zuordnung

<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) Servlet-Code

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");
} 
  }
DTB
quelle
3
Diese Frage bezieht sich auf Javascript, sie hat nichts mit Javascript zu tun.
victorpacheco3107
Diese Frage ist mehr über sessionStorage und localStorage
RR1112