Ich habe eine AngularJS Single Page-Anwendung mit UI -Router implementiert .
Ursprünglich identifizierte ich jeden Zustand mit einer eigenen URL, was jedoch zu unfreundlichen, GUID-gepackten URLs führte.
Deshalb habe ich meine Site jetzt als eine viel einfachere Zustandsmaschine definiert. Die Zustände werden nicht durch URLs identifiziert, sondern einfach nach Bedarf wie folgt geändert:
Verschachtelte Zustände definieren
angular
.module 'app', ['ui.router']
.config ($stateProvider) ->
$stateProvider
.state 'main',
templateUrl: 'main.html'
controller: 'mainCtrl'
params: ['locationId']
.state 'folder',
templateUrl: 'folder.html'
parent: 'main'
controller: 'folderCtrl'
resolve:
folder:(apiService) -> apiService.get '#base/folder/#locationId'
Übergang in einen definierten Zustand
#The ui-sref attrib transitions to the 'folder' state
a(ui-sref="folder({locationId:'{{folder.Id}}'})")
| {{ folder.Name }}
Dieses System funktioniert sehr gut und ich liebe seine saubere Syntax. Da ich jedoch keine URLs verwende, funktioniert der Zurück-Button nicht.
Wie behalte ich meine ordentliche UI-Router-Zustandsmaschine bei, aktiviere aber die Back-Button-Funktionalität?
javascript
angularjs
coffeescript
angular-ui-router
Biofractal
quelle
quelle
Antworten:
Hinweis
Die Antworten, die die Verwendung von Variationen von vorschlagen,
$window.history.back()
haben alle einen entscheidenden Teil der Frage übersehen: Wie kann der Status der Anwendung beim Springen des Verlaufs an den richtigen Status zurückgesetzt werden (Zurück / Vorwärts / Aktualisieren)? In diesem Sinne; Bitte lesen Sie weiter.Ja, es ist möglich, den Browser vor / zurück (Verlauf) zu halten und zu aktualisieren, während eine reine
ui-router
Zustandsmaschine ausgeführt wird, aber es ist ein wenig erforderlich.Sie benötigen mehrere Komponenten:
Eindeutige URLs . Der Browser aktiviert die Vor- / Zurück-Schaltflächen nur, wenn Sie URLs ändern. Daher müssen Sie pro besuchtem Status eine eindeutige URL generieren. Diese URLs müssen jedoch keine Statusinformationen enthalten.
Ein Sitzungsdienst . Jede generierte URL ist mit einem bestimmten Status korreliert, sodass Sie eine Möglichkeit zum Speichern Ihrer URL-Status-Paare benötigen, damit Sie die Statusinformationen abrufen können, nachdem Ihre eckige App durch Zurück / Vorwärts- oder Aktualisierungsklicks neu gestartet wurde.
Eine Staatsgeschichte . Ein einfaches Wörterbuch mit UI-Router-Status, das durch eine eindeutige URL gekennzeichnet ist. Wenn Sie sich auf HTML5 verlassen können, können Sie die HTML5-Verlaufs-API verwenden . Wenn Sie dies jedoch nicht können, können Sie sie selbst in wenigen Codezeilen implementieren (siehe unten).
Ein Ortungsdienst . Schließlich müssen Sie in der Lage sein, sowohl Statusänderungen des UI-Routers, die intern durch Ihren Code ausgelöst werden, als auch normale Änderungen der Browser-URL zu verwalten, die normalerweise durch das Klicken des Benutzers auf Browser-Schaltflächen oder das Eingeben von Inhalten in die Browserleiste ausgelöst werden. Dies kann alles etwas schwierig werden, da es leicht zu verwechseln ist, was was ausgelöst hat.
Hier ist meine Implementierung jeder dieser Anforderungen. Ich habe alles in drei Dienste gebündelt:
Der Sitzungsdienst
Dies ist ein Wrapper für das Javascript-
sessionStorage
Objekt. Ich habe es hier aus Gründen der Klarheit gekürzt. Eine vollständige Erklärung hierzu finden Sie unter: Wie gehe ich mit der Seitenaktualisierung mit einer AngularJS-Einzelseitenanwendung um?Der Staatliche Geschichtsdienst
Das
StateHistoryService
kümmert sich um das Speichern und Abrufen von historischen Zuständen, die durch generierte, eindeutige URLs verschlüsselt sind. Es ist wirklich nur ein Convenience-Wrapper für ein Objekt im Wörterbuchstil.Der staatliche Ortungsdienst
Das
StateLocationService
behandelt zwei Ereignisse:locationChange . Dies wird aufgerufen, wenn der Speicherort des Browsers geändert wird, normalerweise wenn die Schaltfläche Zurück / Vorwärts / Aktualisieren gedrückt wird oder wenn die App zum ersten Mal gestartet wird oder wenn der Benutzer eine URL eingibt. Wenn ein Status für die aktuelle location.url in der vorhanden
StateHistoryService
ist, wird er verwendet, um den Status über den UI-Router wiederherzustellen$state.go
.stateChange . Dies wird aufgerufen, wenn Sie den Status intern verschieben. Der Name und die Parameter des aktuellen Status werden in der
StateHistoryService
von einer generierten URL eingegebenen URL gespeichert . Diese generierte URL kann alles sein, was Sie wollen, sie kann den Zustand auf eine für Menschen lesbare Weise identifizieren oder nicht. In meinem Fall verwende ich einen Statusparameter plus eine zufällig generierte Folge von Ziffern, die von einem Guid abgeleitet wurden (siehe Fuß für das Guid-Generator-Snippet). Die generierte URL wird in der Browserleiste angezeigt und mit entscheidend zum internen Verlaufsstapel des Browsers hinzugefügt@location.url url
. Es fügt die URL zum Verlaufsstapel des Browsers hinzu, der die Vorwärts- / Zurück-Schaltflächen aktiviert.Das große Problem bei dieser Technik ist, dass das Aufrufen
@location.url url
derstateChange
Methode das$locationChangeSuccess
Ereignis auslöst und somit dielocationChange
Methode aufruft . Gleiches Ausrufen von@state.go
fromlocationChange
löst das$stateChangeSuccess
Ereignis und damit diestateChange
Methode aus. Dies wird sehr verwirrend und bringt den Browserverlauf ohne Ende durcheinander.Die Lösung ist sehr einfach. Sie können sehen, dass das
preventCall
Array als Stapel (pop
undpush
) verwendet wird. Jedes Mal, wenn eine der Methoden aufgerufen wird, wird verhindert, dass die andere Methode nur einmal aufgerufen wird. Diese Technik beeinträchtigt nicht die korrekte Auslösung der $ -Ereignisse und hält alles gerade.Jetzt müssen wir nur noch die
HistoryService
Methoden zum richtigen Zeitpunkt im Lebenszyklus des Zustandsübergangs aufrufen . Dies geschieht in der AngularJS Apps-.run
Methode wie folgt :Winkel app.run
Generieren Sie eine Guid
Wenn dies alles vorhanden ist, funktionieren die Vorwärts- / Rückwärts-Tasten und die Aktualisierungs-Taste wie erwartet.
quelle
@setStorage
und@getStorage
nicht "@ get / setSession" verwenden.$window.history.back()
haben einen entscheidenden Teil der Frage übersehen. Es ging darum, den Status der Anwendung wiederherzustellen an der richtigen Position wenn der Verlauf springt (zurück / vorwärts / aktualisieren). Dies würde normalerweise durch die Bereitstellung der Statusdaten über den URI erreicht. Bei der Frage wurde gefragt, wie zwischen Statuspositionen ohne (explizite) URI-Statusdaten gesprungen werden soll. Angesichts dieser Einschränkung reicht es nicht aus, nur die Zurück-Schaltfläche zu replizieren, da dies auf den URI-Statusdaten beruht, um den Statusspeicherort wiederherzustellen.quelle
$window.history.back
der Klarheit macht die Magie nicht$rootScope
... also könnte das Zurückgehen an Ihren Navigationsbereich gebunden sein, wenn Sie möchten.$window.history.back();
Funktion ein, die aufgerufen werden sollng-click
.Nachdem ich verschiedene Vorschläge getestet hatte, stellte ich fest, dass der einfachste Weg oft der beste ist.
Wenn Sie einen eckigen UI-Router verwenden und eine Schaltfläche benötigen, um am besten zurückzukehren, ist dies:
oder
// Warnung setze nicht die href, sonst wird der Pfad unterbrochen.
Erläuterung: Angenommen, eine Standardverwaltungsanwendung. Suchobjekt -> Objekt anzeigen -> Objekt bearbeiten
Verwendung der Winkellösungen Aus diesem Zustand:
An:
Nun, das wollten wir, außer wenn Sie jetzt auf die Schaltfläche "Zurück" des Browsers klicken, sind Sie wieder da:
Und das ist nicht logisch
Jedoch mit der einfachen Lösung
von :
nach dem Klicken auf die Schaltfläche:
nach dem Klicken auf die Zurück-Schaltfläche des Browsers:
Konsistenz wird respektiert. :-)
quelle
Wenn Sie nach dem einfachsten "Zurück" -Button suchen, können Sie eine Direktive wie folgt einrichten:
Beachten Sie, dass dies eine ziemlich unintelligente Schaltfläche "Zurück" ist, da sie den Verlauf des Browsers verwendet. Wenn Sie es auf Ihrer Zielseite einfügen, wird ein Benutzer zu jeder URL zurückgeschickt, von der er vor der Landung auf Ihrer stammt.
quelle
Lösung für die Zurück / Vorwärts-Schaltfläche des Browsers
Ich habe das gleiche Problem festgestellt und es mit dem
popstate event
Objekt aus dem $ -Fenster und gelöstui-router's $state object
. Jedes Mal, wenn sich der aktive Verlaufseintrag ändert, wird ein Popstate-Ereignis an das Fenster gesendet.Die
$stateChangeSuccess
und$locationChangeSuccess
Ereignisse werden beim Klicken auf die Schaltfläche des Browsers nicht ausgelöst, obwohl die Adressleiste den neuen Speicherort anzeigt.Also, vorausgesetzt , Sie von den Zuständen gesteuert haben ,
main
umfolder
zumain
wieder, wenn sie getroffen werdenback
im Browser, sollten Sie zurück zu dem seinfolder
Weg. Der Pfad wird aktualisiert, aber in der Ansicht wird nicht angezeigt, worauf Sie sich befindenmain
. Versuche dies:Die Zurück / Vorwärts-Tasten sollten danach reibungslos funktionieren.
Hinweis: Überprüfen Sie die Browserkompatibilität für window.onpopstate (), um sicherzugehen
quelle
Kann mit einer einfachen Direktive "Go-Back-History" gelöst werden. Diese schließt auch das Fenster, falls keine Vorgeschichte vorhanden ist.
Verwendung der Richtlinie
Erklärung der Winkelrichtlinie
Hinweis: Arbeiten mit UI-Router oder nicht.
quelle
Die Schaltfläche "Zurück" funktionierte auch bei mir nicht, aber ich stellte fest, dass das Problem darin bestand, dass ich
html
Inhalt auf meiner Hauptseite imui-view
Element hatte.dh
Also habe ich den Inhalt in eine neue
.html
Datei verschoben und ihn als Vorlage in der.js
Datei mit den Routen markiert .dh
quelle
history.back()
und in den vorherigen Zustand wechseln oft nicht den gewünschten Effekt. Wenn Sie beispielsweise ein Formular mit Registerkarten haben und jede Registerkarte einen eigenen Status hat, wird die zuvor ausgewählte Registerkarte umgeschaltet und nicht vom Formular zurückgegeben. Bei verschachtelten Zuständen müssen Sie normalerweise über die übergeordneten Zustände nachdenken, die Sie zurücksetzen möchten.Diese Richtlinie löst das Problem
Es kehrt zu dem Zustand zurück, der aktiv war, bevor die Schaltfläche angezeigt wurde. Optional
defaultState
ist der Statusname, der verwendet wird, wenn kein vorheriger Status im Speicher vorhanden ist. Außerdem wird die Bildlaufposition wiederhergestelltCode
quelle