2013-02-19 6 views
22

Durch Aktivierung des HTML5-Modus in AngularJS schreibt der Dienst $location URLs neu, um den Hashbang aus ihnen zu entfernen. Dies ist ein großartiges Feature, das mir bei meiner Anwendung helfen wird, aber es gibt ein Problem mit seinem Fallback auf den Hashbang-Modus. Mein Dienst erfordert Authentifizierung, und ich bin gezwungen, einen externen Authentifizierungsmechanismus aus meiner Anwendung zu verwenden. Wenn ein Nutzer versucht, mit einem Hashbang zu einer URL für meine App zu gelangen, leitet er diese zunächst zur Authentifizierungsseite um (er wird meinen Service nie berühren, wenn er nicht erfolgreich authentifiziert wurde) und leitet sie dann zurück an meine Anwendung. Da das Hash-Tag nur von der Client-Seite aus gesehen wird, wird es bis zum Zeitpunkt, wenn es auf meinen Server trifft, alle Teile der Routen verlassen. Sobald sie authentifiziert sind, können sie die URL erneut eingeben und es wird funktionieren, aber es ist diese eine Anfangszeit, die eine Unterbrechung der Benutzererfahrung verursachen wird.AngularJS HTML5-Modus wird anstelle von Hashbang zu vollständigen Seitenladevorgängen degradiert

Meine Frage ist dann, gibt es einen Weg von $location.html5Mode(true) zum Fallback der vollen Seite neu laden für un-unterstützende Browser, überspringen die Hashbang-Methode des Routing vollständig in AngularJS?

Der beste Vergleich der verfügbaren Implementierungen dessen, was ich anstrebe, wäre etwas wie das Durchsuchen von Ordnern auf github.com. Wenn der Browser das Umschreiben der URL unterstützt, ohne eine Seitenaktualisierung zu starten, lädt die Seite die erforderlichen Teile asynchron. Wenn der Browser dies nicht unterstützt, wenn ein Benutzer auf einen Ordner klickt, wird eine vollständige Seite aktualisiert. Kann dies mit AngularJS anstelle des Hashbang-Modus erreicht werden?

+1

Haben Sie schon einmal mit einer Lösung dieses Problems kommen? Ich stehe vor einer ähnlichen Situation. – Jonathan

Antwort

1

Try $ Lage und $ routeProvider Konfiguration in Browser HTML5 History API Kontrolle zu wickeln, wie folgt aus:

if (isBrowserSupportsHistoryAPI()) { 
    $location.html5Mode(true) 
    $routeProvider.when(...); 
} 

Auch sein können Sie einen Wrapper zu $ ​​Lage erstellen müssen, wenn Sie es verwenden, den Pfad zu ändern. (Sorry für schreckliches Englisch)

1

Warum nicht die nicht authentifizierte Weiterleitung auf der Clientseite für diese Situation behandeln? Ich würde braucht ein bisschen mehr über genau wissen, wie Ihre App funktionieren Ihnen präzise Lösung zu geben, aber im Wesentlichen so etwas wie:

  1. Benutzer auf eine Strecke von AngularJS behandelt gehen, Server die AngularJS Hauptvorlage dient und JavaScript ist
  2. Benutzer nicht authentifiziert ist, erkennt AngularJS diese und leitet auf die Authentifizierungsseite

Sie etwas im Laufblock des Moduls für, wenn die AngularJS Anwendung gestartet haben könnte:

module('app',[]) 
    .configure(...yadda...yadda...yadda...) 
    .run(['$location', 'authenticationService', function($location, auth) { 
    if (!auth.isAuthenticated()) { 
     $location.url(authenticationUrl) 
    } 
    }); 

Ich habe in einem Dienst substriert, der herausfinden würde, ob Sie irgendwie authentifiziert wurden, bis zu Ihnen, wie man einen Sitzungscookie überprüfen könnte, könnte Ihre API treffen, um zu fragen. Es hängt wirklich davon ab, wie Sie die Authentifizierung während der Ausführung der Clientanwendung weiterhin überprüfen möchten.

1

Sie können versuchen, die Funktionalität des $ location-Dienstes zu überschreiben. Die allgemeine Idee wäre, die URL neu zu schreiben, je nachdem, ob jemand bereits authentifiziert ist oder nicht, oder nur einen einzigen Ansatz (ohne Hashbangs) für alle URLs verwendet, unabhängig davon, ob html5mode aktiviert ist oder nicht.

Ich bin mir nicht sicher, ob ich den Anwendungsfall vollständig verstehe, daher kann ich nicht den genauen Code schreiben, den Sie brauchen.Hier ist eine Beispielimplementierung, wie/Arbeitsgeräte überschreibt und registriert den $ Standortdienst, nur um sicherzustellen, dass Hash-Bang ist immer eliminiert:

app.service('$location', [function() { 
    var DEFAULT_PORTS = { 
     ftp: 21, 
     http: 80, 
     https: 443 
    }; 

    angular.extend(this, { 
     absUrl: function() { 
      return location.href; 
     }, 
     hash: function(hash) { 
      return location.hash.substr(1); 
     }, 
     host: function() { 
      return location.host; 
     }, 
     path: function(path) { 
      if (!path) { 
       return location.pathname; 
      } 
      location.pathname = path; 
      return this; 
     }, 
     port: function() { 
      return location.port ? Number(location.port) : DEFAULT_PORTS[this.protocol()] || null; 
     }, 
     protocol: function() { 
      return location.protocol.substr(0, location.protocol.length - 1); 
     }, 
     replace: function() { 
      return this; 
     }, 
     search: function(search, paramValue) { 
      if (search || paramValue) { 
       return this; 
      } 
      var query = {}; 
      location.search.substr(1).split("&").forEach(function(pair) { 
       pair = pair.split("="); query[pair[0]] = decodeURIComponent(pair[1]); 
      }); 
      return query; 
     }, 
     url: function(url, replace) { 
      return this.path(); 
     } 
    }); 
}]); 
2

NICHT die Kernfunktionalität zu überschreiben.

Verwenden Sie Modernizr, Feature-Erkennung, und fahren Sie dann entsprechend fort.

Check für Geschichte API-Unterstützung

if (Modernizr.history) { 
    // history management works! 
} else { 
    // no history support :(
    // fall back to a scripted solution like History.js 
} 
Verwandte Themen