Enrutamiento AngularJS sin el hash '#'

223

Estoy aprendiendo AngularJS y hay una cosa que realmente me molesta.

Yo uso $routeProviderpara declarar reglas de enrutamiento para mi aplicación:

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

pero cuando navego a mi aplicación en el navegador, veo en app/#/testlugar de app/test.

Entonces, mi pregunta es ¿por qué AngularJS agrega este hash #a las URL? ¿Hay alguna posibilidad de evitarlo?

pikkvile
fuente
2
Aquí está la solución si está utilizando Angular 1.6.
Mistalis

Respuestas:

265

De hecho, necesita el # (hashtag) para navegadores que no sean HTML5.

De lo contrario, solo harán una llamada HTTP al servidor en el href mencionado. El # es un cortocircuito de navegador antiguo que no activa la solicitud, lo que permite que muchos frameworks js construyan su propio redireccionamiento en el lado del cliente.

Puede usar $locationProvider.html5Mode(true)para decirle a angular que use la estrategia HTML5 si está disponible.

Aquí la lista de navegadores que admiten la estrategia HTML5: http://caniuse.com/#feat=history

más-
fuente
44
Ok, gracias. Esto es algo que sospechaba. Pero en cuanto a mí, ¡esto es muy poco amigable para el usuario! Digamos que quiero que algún recurso esté disponible a través de url, app / res. ¿Cómo pueden los usuarios de mi sitio descubrir que deberían escribir app / # / res en su lugar?
pikkvile
55
Pero si es así, ¿por qué necesito que estos caminos sean visibles en la barra de ubicación? Si los usuarios no los usan, puedo hacer una aplicación de JavaScript de una sola página.
pikkvile
66
Es útil cuando desea realizar un seguimiento del estado de la aplicación. Los marcos ofrecen un mecanismo de historia. Además, permite el acceso directo al estado de su aplicación a través del intercambio de URL, por ejemplo
más el
66
El hashtag no es obligatorio en los navegadores modernos que admiten la API de historial HTML5. Vea la respuesta de @ skeep y los enlaces provistos. En modo HTML5, Angular solo usará hashtags si el navegador no lo admite. Tenga en cuenta también que no tiene que usar $ routeProvider si no desea ... puede conectar su propia ruta usando ng-clicks y ng-include (en realidad, debe hacerlo si necesita múltiples niveles de enrutamiento, ya que ng-view solo puede aparecer una vez por página). Ver también stackoverflow.com/questions/12793609/…
Mark Rajcok
2
Para el caso html de renderizado hashbang / pushstate / lado del servidor, el de Twitter es bastante bueno para leer engineering.twitter.com/2012/12/… Explica cómo lograron hacerlo, por lo que es compatible con el navegador antiguo y con la búsqueda motores Sé que no es angularjs específico, pero puedes reproducir el flujo.
jackdbernier
47

Si habilitó html5mode como lo han dicho otros, y cree un .htaccessarchivo con los siguientes contenidos (ajuste según sus necesidades):

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]

Los usuarios serán dirigidos a su aplicación cuando ingresen una ruta adecuada, y su aplicación leerá la ruta y la llevará a la "página" correcta dentro de ella.

EDITAR: solo asegúrese de no tener ningún nombre de archivo o directorio en conflicto con sus rutas.

novio
fuente
¿hay una versión nginx de esto? cuando cargo /aboutla página falla a menos que acceda a través de la aplicación.
chovy
Nunca los usé, pero intente esto: stackoverflow.com/questions/5840497/convert-htaccess-to-nginx
bearfriend
3
@chovy: aquí va la versión nGinx: servidor {server_name my-app; raíz / ruta / a / aplicación; ubicación / {try_files $ uri $ uri / /index.html; }}
Moin Haidar
44
recuerde <base href = "/"> </base> en la etiqueta principal
Silvio Troia
¡Gracias! sin esto, la vinculación profunda es imposible. Todavía no estoy seguro de que la belleza o los URI valgan la pena de mantener esto si necesita un enlace profundo, especialmente en algunos entornos de nube / paas donde es posible que no tenga fácil acceso a la configuración httpd.
Pierre Henry
39

Vamos a escribir una respuesta que parezca simple y corta

En el enrutador al final, agregue html5Mode (verdadero) ;

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

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

    $locationProvider.html5Mode(true);
})

En la cabeza html, agregue la etiqueta base

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

gracias a @plus - por detallar la respuesta anterior

vijay
fuente
No he podido hacer que esto funcione. He publicado una nueva pregunta con mis detalles específicos en: stackoverflow.com/questions/36041074/… Mire esto y, si puede ayudar, lo agradecería enormemente.
Larry Martell
30

tratar

$locationProvider.html5Mode(true)

Más información en $ locationProvider
Using $ location

asqueroso
fuente
66
lo siento, agregué .config (function ($ locationProvider) {$ locationProvider.html5Mode (true)}) pero tengo el resultado index.html #% 2Home not index.html / home
zloctb
12

La siguiente información es de:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

Es muy fácil obtener URL limpias y eliminar el hashtag de la URL en Angular.
Por defecto, AngularJS enrutará las URL con un hashtag. Por ejemplo:

Hay 2 cosas que deben hacerse.

  • Configurar $ locationProvider

  • Establecer nuestra base para enlaces relativos

  • $ servicio de ubicación

En Angular, el servicio $ location analiza la URL en la barra de direcciones y realiza cambios en su aplicación y viceversa.

Recomiendo leer los documentos oficiales de Angular $ para conocer el servicio de ubicación y lo que ofrece.

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

$ locationProvider y html5Mode

  • Usaremos el módulo $ locationProvider y estableceremos html5Mode en true.
  • Haremos esto al definir su aplicación Angular y configurar sus rutas.

    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); });

¿Qué es la API de historial HTML5? Es una forma estandarizada de manipular el historial del navegador mediante un script. Esto le permite a Angular cambiar el enrutamiento y las URL de nuestras páginas sin actualizar la página. Para obtener más información sobre esto, aquí hay un buen artículo de API de historial HTML5:

http://diveintohtml5.info/history.html

Configuración para enlaces relativos

  • Para enlazar alrededor de su aplicación usando enlaces relativos, necesitará configurar el <base>en <head>su documento. Esto puede estar en el archivo raíz index.html de su aplicación Angular. Busque la <base>etiqueta y configúrela en la URL raíz que desea para su aplicación.

Por ejemplo: <base href="https://stackoverflow.com/">

  • Hay muchas otras formas de configurar esto, y el modo HTML5 configurado en verdadero debería resolver automáticamente los enlaces relativos. Si la raíz de su aplicación es diferente a la url (por ejemplo / my-base, entonces úsela como su base.

Reserva para navegadores antiguos

  • El servicio $ location recurrirá automáticamente al método hashbang para los navegadores que no admiten la API de historial HTML5.
  • Esto le sucede de manera transparente y no tendrá que configurar nada para que funcione. Desde los documentos de ubicación Angular $, puede ver el método alternativo y cómo funciona.

En conclusión

  • Esta es una manera simple de obtener URL bonitas y eliminar el hashtag en su aplicación Angular. ¡Diviértete haciendo esas aplicaciones angulares súper limpias y súper rápidas!
zero_cool
fuente
3

Si desea configurar esto localmente en OS X 10.8 que sirve Angular con Apache, puede encontrar lo siguiente en su archivo .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>

Las opciones + Seguir enlaces simbólicos si no se configuran pueden generar un error prohibido en los registros de la siguiente manera:

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

Se requiere reescribir la base; de ​​lo contrario, las solicitudes se resolverán en la raíz del servidor, que localmente no es el directorio del proyecto a menos que haya configurado específicamente sus vhosts, por lo que debe establecer la ruta para que la solicitud encuentre el directorio raíz del proyecto. Por ejemplo, en mi máquina tengo un directorio / Users / me / Sites donde guardo todos mis proyectos. Al igual que la antigua configuración de OS X.

Las siguientes dos líneas dicen efectivamente si la ruta no es un directorio o un archivo, por lo que debe asegurarse de que no tiene archivos o directorios iguales a las rutas de ruta de su aplicación.

La siguiente condición dice que si la solicitud no termina con las extensiones de archivo especificadas, agregue lo que necesita allí

Y el último [L] dice que sirve el archivo index.html, su aplicación para todas las demás solicitudes.

Si todavía tiene problemas, verifique el registro de apache, probablemente le dará consejos útiles:

/private/var/log/apache2/error_log
Señor P
fuente
Si usa MAMP como su servidor local de apache, asegúrese de que el primer RewriteBase sea un enlace relativo. por ejemplo, RewriteBase / angularjs_site_folder /
David Douglas
3

El uso del modo HTML5 requiere la reescritura de URL en el lado del servidor, básicamente debe reescribir todos sus enlaces al punto de entrada de su aplicación (por ejemplo, index.html). Requerir una <base>etiqueta también es importante para este caso, ya que permite que AngularJS diferencie entre la parte de la URL que es la base de la aplicación y la ruta que debe manejar la aplicación. Para obtener más información, consulte la Guía del desarrollador de AngularJS: uso del modo $ location HTML5 del lado del servidor .


Actualizar

Cómo: configurar su servidor para que funcione con html5Mode 1

Cuando tenga habilitado html5Mode, el #personaje ya no se usará en sus URL. El #símbolo es útil porque no requiere configuración del lado del servidor. Sin #, la url se ve mucho mejor, pero también requiere reescrituras del lado del servidor. Aquí hay unos ejemplos:

Apache reescribe

<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 reescribe

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

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

Azure IIS reescribe

<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>

Reescribe Express

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

Ver también

georgeawg
fuente
1

En Angular 6, con su enrutador puede usar:

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

También puede usar el siguiente código para redirigir a la página principal (inicio):

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

Después de especificar su redirección como se indicó anteriormente, puede redirigir las otras páginas, por ejemplo:

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

** **

Se recomienda utilizar el estilo HTML 5 (PathLocationStrategy) como estrategia de ubicación en Angular

** porque

  1. Produce las URL limpias y SEO Friendly que son más fáciles de entender y recordar para los usuarios.
  2. Puede aprovechar la representación del lado del servidor, que hará que nuestra aplicación se cargue más rápido, renderizando primero las páginas en el servidor antes de entregarlo al cliente.

Use Hashlocationstrtegy solo si tiene que admitir los navegadores más antiguos.

Haga clic aquí para saber más

Mahendra Waykos
fuente