Ich verwende die Verlaufs-API für meine Web-App und habe ein Problem. Ich rufe Ajax auf, um einige Ergebnisse auf der Seite zu aktualisieren, und verwende history.pushState () , um die Standortleiste des Browsers zu aktualisieren, ohne die Seite neu zu laden. Dann benutze ich natürlich window.popstate , um den vorherigen Status wiederherzustellen, wenn auf die Schaltfläche "Zurück" geklickt wird.
Das Problem ist bekannt - Chrome und Firefox behandeln dieses Popstate-Ereignis unterschiedlich. Während Firefox es beim ersten Laden nicht startet, tut es Chrome. Ich möchte einen Firefox-Stil haben und das Ereignis nicht beim Laden auslösen, da es nur die Ergebnisse mit genau den gleichen beim Laden aktualisiert. Gibt es eine Problemumgehung außer der Verwendung von History.js ? Der Grund, warum ich keine Lust habe, es zu verwenden, ist, dass es viel zu viele JS-Bibliotheken für sich benötigt. Da es in einem CMS mit bereits zu viel JS implementiert werden muss, möchte ich das von mir eingefügte JS minimieren .
Ich möchte also wissen, ob es eine Möglichkeit gibt, Chrome dazu zu bringen, "popstate" beim Laden nicht zu starten, oder ob jemand versucht hat, History.js zu verwenden, da alle Bibliotheken zu einer Datei zusammengefasst sind.
Antworten:
In Google Chrome in Version 19 funktionierte die Lösung von @spliter nicht mehr. Wie @johnnymire hervorhob, existiert history.state in Chrome 19, ist aber null.
Meine Problemumgehung besteht darin, window.history.state! == null hinzuzufügen, um zu überprüfen, ob der Status in window.history vorhanden ist:
Ich habe es in allen gängigen Browsern und in den Chrome-Versionen 19 und 18 getestet. Es sieht so aus, als ob es funktioniert.
quelle
in
undnull
überprüfen, nur!= null
weil sich das auch darum kümmern wirdundefined
.null
in Ihrenhistory.pushState()
Methoden immer wie verwendenhistory.pushState(null,null,'http//example.com/)
. Zugegeben, das würde wahrscheinlich am meisten verwendet werden (so ist es in jquery.pjax.js und den meisten anderen Demos eingerichtet). Aber wenn der Browser implementiertwindow.history.state
(wie FF und Chrome 19+), könnte window.history.state bei einer Aktualisierung oder nach einem Neustart des Browsers ungleich Null seinFalls Sie nicht für jeden Handler, den Sie zu onpopstate hinzufügen, besondere Maßnahmen ergreifen möchten, ist meine Lösung möglicherweise für Sie interessant. Ein großes Plus dieser Lösung ist auch, dass Onpopstate-Ereignisse behandelt werden können, bevor das Laden der Seite abgeschlossen ist.
Führen Sie diesen Code einfach einmal aus, bevor Sie Onpopstate-Handler hinzufügen, und alles sollte wie erwartet funktionieren (auch bekannt als in Mozilla ^^) .
Wie es funktioniert:
Chrome, Safari und wahrscheinlich andere Webkit-Browser lösen das Ereignis onpopstate aus, wenn das Dokument geladen wurde. Dies ist nicht beabsichtigt, daher blockieren wir Popstate-Ereignisse bis zur ersten Ereignisschleife nach dem Laden des Dokuments. Dies erfolgt durch die Aufrufe von präventDefault und stopImmediatePropagation (im Gegensatz zu stopPropagation stoppt stopImmediatePropagation alle Aufrufe der Ereignishandler sofort).Da der readyState des Dokuments jedoch bereits "vollständig" ist, wenn Chrome fälschlicherweise onpopstate auslöst, lassen wir opopstate-Ereignisse zu, die ausgelöst wurden, bevor das Laden des Dokuments abgeschlossen wurde, um onpopstate-Aufrufe zu ermöglichen, bevor das Dokument geladen wurde.
Update 2014-04-23: Es wurde ein Fehler behoben, durch den Popstate-Ereignisse blockiert wurden, wenn das Skript nach dem Laden der Seite ausgeführt wurde.
quelle
window.history.state
schlägt beim erneuten Laden fehl, wenn ein Status festgelegt wurde. Festlegen der Variablen vor dem Code von pushState Clutters. Ihre Lösung ist elegant und kann über andere Skripte gelegt werden, ohne den Rest der Codebasis zu beeinträchtigen. Vielen Dank.Die Verwendung von setTimeout ist keine korrekte Lösung, da Sie nicht wissen, wie lange das Laden des Inhalts dauern wird, sodass das Popstate-Ereignis möglicherweise nach dem Timeout ausgegeben wird.
Hier ist meine Lösung: https://gist.github.com/3551566
quelle
Die Lösung wurde in gefunden den Zeilen 195-225 von jquery.pjax.j :
quelle
Eine direktere Lösung als die Neuimplementierung von pjax besteht darin, eine Variable in pushState festzulegen und in popState nach der Variablen zu suchen, damit der anfängliche popState beim Laden nicht inkonsistent ausgelöst wird (keine jquery-spezifische Lösung, die nur für Ereignisse verwendet wird):
quelle
window.history.ready
ist immer wahr.!window.history.ready && !ev.originalEvent.state
- Diese beiden Dinge werden nie definiert, wenn ich die Seite aktualisiere. Daher wird kein Code ausgeführt.Dem ersten onpopstate- Ereignis von Webkit ist kein Status zugewiesen. Sie können dies also verwenden, um nach unerwünschtem Verhalten zu suchen :
Eine umfassende Lösung, die die Navigation zurück zur ursprünglichen Seite ermöglicht, würde auf dieser Idee aufbauen:
Während dies immer noch zweimal ausgelöst werden könnte (mit einer raffinierten Navigation), kann es einfach mit einem Check gegen die vorherige href behandelt werden.
quelle
window.history.state
auch unter iOS null ist. Es reicht aus, nur zu überprüfen, ob die Eigenschaft e.state null ist.Dies ist meine Problemumgehung.
quelle
Hier ist meine Lösung:
quelle
Der beste Weg, um Chrome dazu zu bringen, Popstate beim Laden einer Seite nicht auszulösen, besteht darin, https://code.google.com/p/chromium/issues/detail?id=63040 hochzustimmen . Sie wissen, dass Chrome seit zwei Jahren nicht mehr mit der HTML5-Spezifikation übereinstimmt und haben es immer noch nicht behoben!
quelle
Im Falle einer Verwendung
event.state !== null
funktioniert die Rückkehr zum Verlauf zur zuerst geladenen Seite in nicht mobilen Browsern nicht. Ich benutze sessionStorage, um zu markieren, wann die Ajax-Navigation wirklich beginnt.quelle
Die vorgestellten Lösungen haben ein Problem beim erneuten Laden der Seite. Folgendes scheint besser zu funktionieren, aber ich habe nur Firefox und Chrome getestet. Es nutzt die Aktualität, dass es einen Unterschied zwischen
e.event.state
und zu geben scheintwindow.history.state
.quelle
e.event
ist undefiniertIch weiß, dass Sie dagegen gefragt haben, aber Sie sollten wirklich nur History.js verwenden, da es eine Million Browser-Inkompatibilitäten beseitigt. Ich bin nur die manuelle Reparaturroute gegangen, um später festzustellen, dass es immer mehr Probleme gab, die Sie erst später herausfinden werden. Es ist heutzutage wirklich nicht so schwer:
Und lesen Sie die API unter https://github.com/browserstate/history.js
quelle
Dies löste das Problem für mich. Ich habe lediglich eine Timeout-Funktion festgelegt, die die Ausführung der Funktion so lange verzögert, dass das Popstate-Ereignis, das beim Laden der Seite ausgelöst wird, übersehen wird
quelle
Sie können ein Ereignis erstellen und es nach Ihrem Onload-Handler auslösen.
Beachten Sie, dass dies in Chrome / Safari etwas kaputt ist, aber ich habe den Patch bei WebKit eingereicht und er sollte bald verfügbar sein, aber es ist der "korrekteste" Weg.
quelle
Dies funktionierte bei mir in Firefox und Chrome
quelle