$ posizione / passaggio tra html5 e hashbang mode / link rewriting

Ho avuto l’impressione che Angular avrebbe riscritto gli URL che appaiono negli attributi href dei tag di ancoraggio all’interno di tempaltes, in modo che funzionassero sia in modalità html5 che in modalità hashbang. La documentazione per il servizio di localizzazione sembra dire che il riscrittura HTML Link si occupa della situazione di hashbang. Mi aspetterei quindi che, quando non sono in modalità HTML5, gli hash vengano inseriti e, in modalità HTML5, non lo facciano.

Tuttavia, sembra che non ci sia alcuna riscrittura. L’esempio seguente non mi consente semplicemente di cambiare la modalità. Tutti i collegamenti nell’applicazione dovrebbero essere riscritti a mano (o derivati ​​da una variabile in fase di esecuzione. Devo riscrivere manualmente tutti gli URL in base alla modalità?

Non vedo alcuna riscrittura di URL lato client in corso in Angular 1.0.6, 1.1.4 o 1.1.3. Sembra che tutti i valori href debbano essere preceduti con # / per la modalità hashbang e / per la modalità html5.

C’è qualche configurazione necessaria per causare la riscrittura? Sto fraintendendo i documenti? Fare qualcos’altro sciocco?

Ecco un piccolo esempio:

        
    angular.module('sample', []) .config( ['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) { //commenting out this line (switching to hashbang mode) breaks the app //-- unless # is added to the templates $locationProvider.html5Mode(true); $routeProvider.when('/', { template: 'this is home. go to about' }); $routeProvider.when('/about', { template: 'this is about. go to home</a' }); } ]) .run();

    Addendum: rileggendo la mia domanda, vedo che ho usato il termine “riscrittura” senza un’abbondanza di chiarezza su chi e quando volevo fare la riscrittura. La domanda riguarda come ottenere Angular per riscrivere gli URL quando esegue il rendering dei percorsi e come ottenerlo per interpretare i percorsi nel codice JS in modo uniforms tra le due modalità. Non si tratta di come fare in modo che un server Web esegua la riscrittura delle richieste compatibile con HTML5.

    La documentazione non è molto chiara sul routing di AngularJS. Parla di Hashbang e della modalità HTML5. In effetti, il routing di AngularJS funziona in tre modalità:

    • Modalità Hashbang
    • Modalità HTML5
    • Hashbang in modalità HTML5

    Per ogni modalità è presente una rispettiva class LocationUrl (LocationHashbangUrl, LocationUrl e LocationHashbangInHTML5Url).

    Per simulare la riscrittura degli URL è necessario impostare html5mode su true e decorare la class $ sniffer come segue:

     $provide.decorator('$sniffer', function($delegate) { $delegate.history = false; return $delegate; }); 

    Ora lo spiegherò in modo più dettagliato:

    Modalità Hashbang

    Configurazione:

     $routeProvider .when('https://stackoverflow.com/path', { templateUrl: 'path.html', }); $locationProvider .html5Mode(false) .hashPrefix('!'); 

    Questo è il caso in cui è necessario utilizzare URL con hash nei file HTML come in

     link 

    Nel browser è necessario utilizzare il seguente link: http://www.example.com/base/index.html#!/basehttps://stackoverflow.com/path

    Come puoi vedere nella pura modalità Hashbang, tutti i collegamenti nei file HTML devono iniziare con la base come “index.html #!”.

    Modalità HTML5

    Configurazione:

     $routeProvider .when('https://stackoverflow.com/path', { templateUrl: 'path.html', }); $locationProvider .html5Mode(true); 

    Dovresti impostare la base nel file HTML

          

    In questa modalità puoi usare i link senza # nei file HTML

     link 

    Collegamento nel browser:

     http://www.example.com/basehttps://stackoverflow.com/path 

    Hashbang in modalità HTML5

    Questa modalità viene triggersta quando effettivamente utilizziamo la modalità HTML5 ma in un browser incompatibile. Possiamo simulare questa modalità in un browser compatibile decorando il servizio $ sniffer e impostando la cronologia su false.

    Configurazione:

     $provide.decorator('$sniffer', function($delegate) { $delegate.history = false; return $delegate; }); $routeProvider .when('https://stackoverflow.com/path', { templateUrl: 'path.html', }); $locationProvider .html5Mode(true) .hashPrefix('!'); 

    Imposta la base nel file HTML:

          

    In questo caso i collegamenti possono anche essere scritti senza l’hash nel file HTML

     link 

    Collegamento nel browser:

     http://www.example.com/index.html#!/basehttps://stackoverflow.com/path 

    Per i futuri lettori, se stai utilizzando Angular 1.6 , devi anche modificare l’ hashPrefix :

     appModule.config(['$locationProvider', function($locationProvider) { $locationProvider.html5Mode(true); $locationProvider.hashPrefix(''); }]); 

    Non dimenticare di impostare la base nel tuo HTML :

       ...  

    Maggiori informazioni sul registro delle modifiche qui .

    Questo mi ci è voluto un po ‘per capire quindi questo è il modo in cui ho funzionato – Angular WebAPI ASP Routing senza # per SEO

    1. aggiungi a Index.html – base href = “/”>
    2. Aggiungi $ locationProvider.html5Mode (true); per app.config

    3. Avevo bisogno di un certo controller (che era nel controller di casa) per essere ignorato per il caricamento delle immagini, quindi ho aggiunto quella regola a RouteConfig

        routes.MapRoute( name: "Default2", url: "Home/{*.}", defaults: new { controller = "Home", action = "SaveImage" } ); 
    4. In Global.asax aggiungi quanto segue: assicurandoti di ignorare le API e i percorsi di caricamento delle immagini, lascia che funzionino normalmente, altrimenti reindirizza tutto il resto.

        private const string ROOT_DOCUMENT = "/Index.html"; protected void Application_BeginRequest(Object sender, EventArgs e) { var path = Request.Url.AbsolutePath; var isApi = path.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase); var isImageUpload = path.StartsWith("/home", StringComparison.InvariantCultureIgnoreCase); if (isApi || isImageUpload) return; string url = Request.Url.LocalPath; if (!System.IO.File.Exists(Context.Server.MapPath(url))) Context.RewritePath(ROOT_DOCUMENT); } 
    5. Assicurati di usare $ location.url (‘/ XXX’) e non window.location … per redirect

    6. Fare riferimento ai file CSS con percorso assoluto

    e non

      

    Nota finale: farlo in questo modo mi dava il pieno controllo e non avevo bisogno di fare nulla per la configurazione web.

    Spero che questo aiuti in quanto mi ci è voluto un po ‘per capire.

    Volevo essere in grado di accedere alla mia applicazione con la modalità HTML5 e un token fisso e quindi passare al metodo hashbang (per mantenere il token in modo che l’utente possa aggiornare la sua pagina).

    URL per accedere alla mia app:

    http://myapp.com/amazing_url?token=super_token

    Quindi, quando l’utente carica la pagina:

    http://myapp.com/amazing_url?token=super_token#/amazing_url

    Quindi, quando l’utente naviga:

    http://myapp.com/amazing_url?token=super_token#/another_url

    Con questo tengo il token nell’URL e mantengo lo stato quando l’utente sta navigando. Ho perso un po ‘di visibilità dell’URL, ma non esiste un modo perfetto per farlo.

    Quindi non abilitare la modalità HTML5 e quindi aggiungere questo controller:

     .config ($stateProvider)-> $stateProvider.state('home-loading', { url: '/', controller: 'homeController' }) .controller 'homeController', ($state, $location)-> if window.location.pathname != '/' $location.url(window.location.pathname+window.location.search).replace() else $state.go('home', {}, { location: 'replace' })