2013-09-25 6 views
34

Ich arbeite an einer AngularJS App, die eine Route alle hat (z. B. .when('/:slug', {...)) die erforderlich ist, um ältere URL-Formate aus einer früheren (nicht eckigen) Version der App zu unterstützen. Der Controller, der auf den Catch reagiert, versucht, ein zugehöriges Objekt zu ziehen. Wenn er nicht gefunden wird, wird er mithilfe der $location.path-Methode auf eine 404-Seite umgeleitet. Dies führt dazu, dass der Benutzer auf die 404-Seite gelangt, aber wenn der Benutzer in seinem Browser zurückkehrt, bringt er sie zurück zu der Seite, die sie an die 404-Seite zwang, und sie können schließlich nicht aus dem Zyklus entkommen.AngularJS Redirect ohne einen Verlaufsstatus

Meine Frage ist, ob es 1) ein besseres Muster für die Behandlung dieser Situation gibt, oder 2) wenn es eine Möglichkeit gibt, den Benutzer umzuleiten, die einen Verlauf Push-Status im Browser nicht erzwingt?

Antwort

56

Sie können die URL ändern, ohne zum Verlaufsstatus hinzuzufügen, gefunden here unter "Methode ersetzen". Dies entspricht im Wesentlichen dem Aufruf von history.replaceState() von HTML5.

Ich habe nicht gefunden, dass es möglich ist, die Ansicht zu ändern, ohne die URL zu ändern. Die einzige Methode zum Ändern der Ansicht, die ich gefunden habe, besteht darin, den Standortpfad zu ändern.

+0

Wollen Sie mit der Methode replace die URL aktualisieren, ohne den Status auf der Seite zu ändern? Ich meine in Bezug auf eine rein kosmetische Wirkung der Änderung der URL? Weil dies die Möglichkeit der Seitenüberlagerungen (mit den richtigen URLs) ähnlich pinterest. – CMCDragonkai

+0

Ich habe das vor einer Weile geschrieben, aber ich denke, dass die Änderung der URL immer noch das Angular-Ereignis zum Umleiten auslöst, aber dies würde verhindern, dass es im Browserverlauf angezeigt wird, so dass zumindest der Zurück-Button immer noch funktioniert. – thrashr888

+3

Schön. Es funktioniert auch mit '.search()' – vtortola

3

Der normale Betrieb des Routensystems besteht darin, dass der Dienst $route das Ereignis $locationChangeSuccess überwacht und dann mit dem Laden einer Route beginnt. Wenn es fertig ist, die Vorlage zu laden, die Lösungsschritte durchzuführen und den Controller zu instanziieren, sendet es seinerseits ein $routeChangeSuccess Ereignis. Das $routeChangeSuccess wird von der Richtlinie ng-view überwacht, und so kann es die Vorlagen und Bereiche austauschen, sobald die neue Route fertig ist.

Mit all den oben genannten, kann es funktionieren Anwendungscode das Verhalten des $route Service emulieren haben, indem die aktuelle Route zu aktualisieren und die Route Änderungsereignis Emittieren der Ansicht zu erhalten zu aktualisieren:

var errorRoute = $route.routes[null]; // assuming the "otherwise" route is the 404 
// a route instance is an object that inherits from the route and adds 
// new properties representing the routeParams and locals. 
var errorRouteInstance = angular.inherit(
    errorRoute, 
    { 
     params: {}, 
     pathParams: {}, 
    } 
); 
// The $route service depends on this being set so it can recover the route 
// for a given route instance. 
errorRouteInstance.$$route = errorRoute; 

var last = $route.current; 
$route.current = errorRouteInstance; 

// the ng-view code doesn't actually care about the parameters here, 
// since it goes straight to $route.current, but we should include 
// them anyway since other code might be listening for this event 
// and depending on these params to behave as documented. 
$rootScope.broadcast('$routeChangeSuccess', errorRoute, last); 

Das obige geht davon aus, dass Ihre "sonst" Route keine "Auflösungs" Schritte hat. Es geht auch davon aus, dass es keine $routeParams erwartet, was natürlich für die "ansonsten" Route gilt, aber möglicherweise nicht wahr ist, wenn Sie eine andere Route verwenden.

Es ist unklar, welche der oben genannten abhängig von Implementierungsdetails vs. Schnittstelle ist. Das $routeChangeSuccess-Ereignis ist sicherlich dokumentiert, aber die $$route-Eigenschaft der Routeninstanz scheint ein Implementierungsdetail des Routensystems zu sein, da es einen Doppel-Dollar-Vornamen hat. Das Detail, dass die "ansonsten" Route in der Routentabelle mit dem Schlüssel null gehalten wird, ist möglicherweise auch ein Implementierungsdetail. Mit all dem gesagt, kann dieses Verhalten in zukünftigen Versionen von AngularJS nicht mehr funktionieren.

Für weitere Informationen können Sie beziehen sich auf the ng-view code that handles this event, was letztlich ist, was der obige Code zu gefallen, zusammen mit the event emitting code, die ich als Grundlage für das obige Beispiel verwendet. Wie Sie aus diesen Links entnehmen können, stammen die Informationen in diesem Beitrag aus dem letzten Master-Zweig von AngularJS, der zum Zeitpunkt des Schreibens als 1.2.0-Snapshot bezeichnet ist.