Routing di AngularJS senza l'hash '#'


223

Sto imparando AngularJS e c'è una cosa che mi dà davvero fastidio.

Uso $routeProviderper dichiarare le regole di routing per la mia applicazione:

$routeProvider.when('/test', {
  controller: TestCtrl,
  templateUrl: 'views/test.html'
})
.otherwise({ redirectTo: '/test' });

ma quando navigo verso la mia app nel browser vedo app/#/testinvece di app/test.

Quindi la mia domanda è: perché AngularJS aggiunge questo hash #agli URL? C'è qualche possibilità per evitarlo?


2
Ecco la soluzione se si utilizza Angular 1.6.
Mistalis,

Risposte:


265

In effetti è necessario il # (hashtag) per i browser non HTML5.

In caso contrario, eseguiranno semplicemente una chiamata HTTP al server all'href menzionato. # È un vecchio cortocircuito del browser che non attiva la richiesta, che consente a molti framework js di costruire il proprio reindirizzamento sul lato client.

Puoi usare $locationProvider.html5Mode(true)per dire ad angolare di usare la strategia HTML5 se disponibile.

Ecco l'elenco dei browser che supportano la strategia HTML5: http://caniuse.com/#feat=history


4
Ok grazie. Questo è qualcosa che sospettavo. Ma per quanto mi riguarda, è piuttosto ostile per l'utente! Diciamo che voglio che alcune risorse siano disponibili tramite url, app / res. In che modo gli utenti del mio sito possono scoprire che dovrebbero invece digitare app / # / res?
pikkvile,

5
Ma se è così, perché ho bisogno che questi percorsi siano visibili nella barra degli indirizzi? Se gli utenti non li usano, posso semplicemente creare un'applicazione javascript a pagina singola.
pikkvile,

6
È utile quando si desidera tenere traccia dello stato dell'applicazione. I framework offrono un meccanismo storico. Inoltre, consente l'accesso diretto uno stato della vostra applicazione tramite la condivisione di URL per esempio
plus-

6
L'hashtag non è richiesto nei browser moderni che supportano l'API della cronologia HTML5. Vedi la risposta di @ skeep e i collegamenti forniti. In modalità HTML5, Angular utilizzerà gli hashtag solo se il browser non lo supporta. Nota anche che non devi usare $ routeProvider se non vuoi ... puoi collegare il tuo routing usando ng-click e ng-include (in realtà devi farlo se hai bisogno di più livelli di routing, poiché ng-view può apparire solo una volta per pagina). Vedere anche stackoverflow.com/questions/12793609/...
Mark Rajcok

2
Per il caso html di rendering hashbang / pushstate / lato server, quello di Twitter è piuttosto carino da leggere engineering.twitter.com/2012/12/… Spiega come sono riusciti a farlo, quindi è retrocompatibile con il vecchio browser e con la ricerca motori. So che non è specifico angularjs ma puoi riprodurre il flusso.
jackdbernier,

47

Se hai abilitato html5mode come altri hanno già detto, e crea un .htaccessfile con i seguenti contenuti (regola le tue esigenze):

RewriteEngine   On
RewriteBase     /
RewriteCond     %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond     %{REQUEST_FILENAME} !-f
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ./index.html [L]

Gli utenti verranno indirizzati alla tua app quando immettono un percorso corretto e la tua app leggerà il percorso e li porterà alla "pagina" corretta al suo interno.

EDIT: assicurati solo di non avere alcun nome di file o directory in conflitto con i tuoi percorsi.


c'è una versione nginx di questo? quando carico /aboutla pagina non riesce a meno che non ci arrivo tramite l'app.
amante


3
@chovy: ecco la versione di nGinx: server {nome_server my-app; root / path / to / app; location / {try_files $ uri $ uri / /index.html; }}
Moin Haidar,

4
ricordare <base href = "/"> </base> nel tag head
Silvio Troia,

Grazie! senza questo, il deep linking è impossibile. Non sono ancora sicuro che la bellezza o gli URI valgano la pena di mantenerlo se hai bisogno di collegamenti diretti, specialmente in alcuni ambienti cloud / paas in cui potresti non avere un facile accesso alla configurazione di httpd.
Pierre Henry,

39

Consente di scrivere una risposta che sembra semplice e breve

Nel router alla fine aggiungi html5Mode (true) ;

app.config(function($routeProvider,$locationProvider) {

    $routeProvider.when('/home', {
        templateUrl:'/html/home.html'
    });

    $locationProvider.html5Mode(true);
})

In html head aggiungi il tag base

<html>
<head>
    <meta charset="utf-8">    
    <base href="/">
</head>

grazie a @plus - per il dettaglio della risposta sopra


Non sono stato in grado di farlo funzionare. Ho pubblicato una nuova domanda con i miei dettagli specifici su: stackoverflow.com/questions/36041074/… Per favore guarda questo e se puoi aiutare lo apprezzerei molto.
Larry Martell,


12

Le seguenti informazioni provengono da:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

È molto facile ottenere URL puliti e rimuovere l'hashtag dall'URL in Angular.
Per impostazione predefinita, AngularJS indirizzerà gli URL con un hashtag, ad esempio:

Ci sono 2 cose che devono essere fatte.

  • Configurazione di $ locationProvider

  • Impostare la nostra base per i collegamenti relativi

  • Servizio $ location

In Angular, il servizio $ location analizza l'URL nella barra degli indirizzi e apporta modifiche all'applicazione e viceversa.

Consiglio vivamente di leggere i documenti ufficiali sulla posizione di Angular $ per avere un'idea del servizio di localizzazione e di ciò che fornisce.

https://docs.angularjs.org/api/ng/service/$location

$ locationProvider e html5Mode

  • Useremo il modulo $ locationProvider e imposteremo html5Mode su true.
  • Lo faremo quando definiremo l'applicazione angolare e configureremo i percorsi.

    angular.module('noHash', [])
    
    .config(function($routeProvider, $locationProvider) {
    
       $routeProvider
           .when('/', {
               templateUrl : 'partials/home.html',
               controller : mainController
           })
           .when('/about', {
               templateUrl : 'partials/about.html',
               controller : mainController
           })
           .when('/contact', {
               templateUrl : 'partials/contact.html',
               controller : mainController
           });
    
       // use the HTML5 History API
       $locationProvider.html5Mode(true); });

Che cos'è l'API della cronologia HTML5? È un modo standardizzato per manipolare la cronologia del browser usando uno script. Ciò consente ad Angular di modificare il routing e gli URL delle nostre pagine senza aggiornare la pagina. Per ulteriori informazioni su questo, ecco un buon articolo API storia HTML5:

http://diveintohtml5.info/history.html

Impostazione per collegamenti relativi

  • Per collegarsi all'applicazione utilizzando i relativi collegamenti, è necessario impostare la <base>in <head>del documento. Potrebbe trovarsi nel file root.html di root della tua app Angular. Trova il <base>tag e impostalo sull'URL di root che desideri per la tua app.

Per esempio: <base href="https://stackoverflow.com/">

  • Esistono molti altri modi per configurarlo e la modalità HTML5 impostata su true dovrebbe risolvere automaticamente i collegamenti relativi. Se la tua radice dell'applicazione è diversa dall'URL (ad esempio / my-base, utilizzalo come base.

Fallback per browser meno recenti

  • Il servizio $ location eseguirà automaticamente il fallback sul metodo hashbang per i browser che non supportano l'API della cronologia HTML5.
  • Questo accade in modo trasparente a te e non dovrai configurare nulla per farlo funzionare. Dai documenti angolari $ location, puoi vedere il metodo di fallback e come funziona.

In conclusione

  • Questo è un modo semplice per ottenere graziosi URL e rimuovere l'hashtag nella tua applicazione Angular. Divertiti a creare quelle app Angular super pulite e super veloci!

3

Se vuoi configurarlo localmente su OS X 10.8 che serve Angular con Apache, potresti trovare quanto segue nel tuo file .htaccess:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /~yourusername/appname/public/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg|jpeg|gif|txt)
    RewriteRule (.*) index.html [L]
</IfModule>

Opzioni + FollowSymlink se non impostati possono darti un errore proibito nei log in questo modo:

Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden

È richiesta la riscrittura della base, altrimenti le richieste verranno risolte nella radice del server che localmente per impostazione predefinita non è la directory del progetto a meno che non siano stati configurati specificamente i vhosts, quindi è necessario impostare il percorso in modo che la richiesta trovi la directory principale del progetto. Ad esempio sul mio computer ho una directory / Users / me / Sites in cui conservo tutti i miei progetti. Come il vecchio OS X installato.

Le due righe successive indicano effettivamente se il percorso non è una directory o un file, quindi è necessario assicurarsi che non vi siano file o directory uguali ai percorsi della route dell'app.

La condizione successiva indica se la richiesta non termina con le estensioni di file specificate, quindi aggiungi ciò di cui hai bisogno

E l'ultimo [L] sta dicendo di servire il file index.html - la tua app per tutte le altre richieste.

Se hai ancora problemi, controlla il registro di Apache, probabilmente ti darà consigli utili:

/private/var/log/apache2/error_log

Se usi MAMP come server apache localhost assicurati che il primo RewriteBase sia un collegamento relativo. es. RewriteBase / angularjs_site_folder /
David Douglas

3

L'uso della modalità HTML5 richiede la riscrittura dell'URL sul lato server, in pratica devi riscrivere tutti i tuoi collegamenti al punto di ingresso della tua applicazione (es. Index.html). La richiesta di un <base>tag è importante anche in questo caso, poiché consente ad AngularJS di distinguere tra la parte dell'URL che costituisce la base dell'applicazione e il percorso che deve essere gestito dall'applicazione. Per ulteriori informazioni, consultare la Guida per gli sviluppatori di AngularJS - Uso della modalità $ location HTML5 lato server .


Aggiornare

Procedura: configurare il server in modo che funzioni con html5Mode 1

Quando hai abilitato html5Mode, il #personaggio non sarà più utilizzato nei tuoi URL. Il #simbolo è utile perché non richiede alcuna configurazione lato server. Senza #, l'URL sembra molto più bello, ma richiede anche riscritture lato server. Ecco alcuni esempi:

Apache Riscrive

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

Nginx Riscrive

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Azure IIS Rewrites

<system.webServer>
  <rewrite>
    <rules> 
      <rule name="Main Rule" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

Express Rewrites

var express = require('express');
var app = express();

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

app.listen(3006); //the port you want to use

Guarda anche


1

In Angular 6, con il router è possibile utilizzare:

RouterModule.forRoot(routes, { useHash: false })

0

È inoltre possibile utilizzare il codice seguente per reindirizzare alla pagina principale (home):

{ path: '', redirectTo: 'home', pathMatch: 'full'}

Dopo aver specificato il reindirizzamento come sopra, puoi reindirizzare le altre pagine, ad esempio:

{ path: 'add-new-registration', component: AddNewRegistrationComponent},
{ path: 'view-registration', component: ViewRegistrationComponent},
{ path: 'home', component: HomeComponent}

0

**

Si consiglia di utilizzare lo stile HTML 5 (PathLocationStrategy) come strategia di localizzazione in angolare

** Perché

  1. Produce URL puliti e SEO friendly che sono più facili da capire e ricordare per gli utenti.
  2. Puoi sfruttare il rendering sul lato server, che renderà più veloce il caricamento della nostra applicazione, eseguendo il rendering delle pagine nel server prima di consegnarlo al client.

Usa Hashlocationstrtegy solo se devi supportare i browser più vecchi.

Clicca qui per saperne di più

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.