routeprovider routechangesuccess route change angularjs angular-routing

routechangesuccess - route change angularjs



$ location/cambio entre html5 y hashbang mode/link rewriting (4)

Tenía la impresión de que Angular volvería a escribir las URL que aparecen en los atributos href de las etiquetas de anclaje dentro de tempaltes, de modo que funcionarían tanto en modo html5 como en modo hashbang. La documentación del servicio de ubicación parece indicar que la reescritura de enlaces HTML se ocupa de la situación de hashbang. Por lo tanto, esperaría que cuando no esté en el modo HTML5, se inserten los hash, y en modo HTML5, no lo harían.

Sin embargo, parece que no se está reescribiendo. El siguiente ejemplo no me permite simplemente cambiar el modo. Todos los enlaces de la aplicación deberían ser reescritos a mano (o derivados de una variable en tiempo de ejecución. ¿Debo reescribir manualmente todas las URL según el modo?

No veo ninguna reescritura de URL del lado del cliente en Angular 1.0.6, 1.1.4 o 1.1.3. Parece que todos los valores href deben ir precedidos de # / para el modo hashbang y / para el modo html5.

¿Hay alguna configuración necesaria para causar la reescritura? ¿Estoy malinterpretando los documentos? ¿Hacer algo más tonto?

Aquí hay un pequeño ejemplo:

<head> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.3/angular.js"></script> </head> <body> <div ng-view></div> <script> 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 <a href="/about"/>about</a>'' }); $routeProvider.when(''/about'', { template: ''this is about. go to <a href="/"/>home</a'' }); } ]) .run(); </script> </body>

Adición: al volver a leer mi pregunta, veo que utilicé el término "reescritura" sin una gran claridad sobre quién y cuándo quería volver a escribir. La pregunta es cómo hacer que Angular reescriba las URL cuando representa las rutas y cómo lograr que interprete las rutas en el código JS uniformemente en los dos modos. No se trata de hacer que un servidor web reescriba las solicitudes compatibles con HTML5.


Esto me llevó un tiempo descubrir que así es como lo conseguí trabajando: Angular WebAPI ASP Routing sin el # para SEO

  1. agregar a Index.html - base href = "/">
  2. Agregar $ locationProvider.html5Mode (true); a app.config

  3. Necesitaba un determinado controlador (que estaba en el controlador del hogar) para ser ignorado para cargar imágenes, así que agregué esa regla a RouteConfig

    routes.MapRoute( name: "Default2", url: "Home/{*.}", defaults: new { controller = "Home", action = "SaveImage" } );

  4. En Global.asax, agregue lo siguiente: asegúrese de ignorar las rutas de carga de imágenes y api para que funcionen con normalidad, de lo contrario, redireccionar todo lo demás.

    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. Asegúrese de utilizar $ location.url (''/ XXX'') y no window.location ... para redirigir

  6. Referencia los archivos CSS con ruta absoluta

y no

<link href="app/content/bootstrapwc.css" rel="stylesheet" />

Nota final: hacerlo de esta manera me dio el control total y no tuve que hacer nada con la configuración web.

Espero que esto ayude ya que esto me tomó un tiempo darme cuenta.


Futuros lectores de Fur, si está usando Angular 1.6 , también necesita cambiar el hashPrefix :

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

No olvides establecer la base en tu HTML <head> :

<head> <base href="/"> ... </head>

Más información sobre el registro de cambios here .


La documentación no es muy clara sobre el enrutamiento AngularJS. Habla sobre Hashbang y el modo HTML5. De hecho, el enrutamiento AngularJS funciona en tres modos:

  • Modo Hashbang
  • Modo HTML5
  • Hashbang en modo HTML5

Para cada modo hay una clase LocationUrl respectiva (LocationHashbangUrl, LocationUrl y LocationHashbangInHTML5Url).

Para simular la reescritura de URL, debe establecer html5mode en verdadero y decorar la clase $ sniffer de la siguiente manera:

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

Ahora voy a explicar esto con más detalle:

Modo Hashbang

Configuración:

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

Este es el caso cuando necesita usar URL con hashes en sus archivos HTML como en

<a href="index.html#!/path">link</a>

En el navegador, debe usar el siguiente enlace: http://www.example.com/base/index.html#!/base/path

Como puede ver en modo Hashbang puro, todos los enlaces en los archivos HTML deben comenzar con la base, como "index.html #!".

Modo HTML5

Configuración:

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

Debes establecer la base en HTML-file

<html> <head> <base href="/"> </head> </html>

En este modo, puede usar enlaces sin el # en archivos HTML

<a href="/path">link</a>

Enlace en el navegador:

http://www.example.com/base/path

Hashbang en modo HTML5

Este modo se activa cuando realmente usamos el modo HTML5 pero en un navegador incompatible. Podemos simular este modo en un navegador compatible decorando el servicio $ sniffer y configurando el historial en falso.

Configuración:

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

Establezca la base en archivo HTML:

<html> <head> <base href="/"> </head> </html>

En este caso, los enlaces también se pueden escribir sin el hash en el archivo HTML

<a href="/path">link</a>

Enlace en el navegador:

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


Quería poder acceder a mi aplicación con el modo HTML5 y un token fijo y luego cambiar al método hashbang (para mantener el token para que el usuario pueda actualizar su página).

URL para acceder a mi aplicación:

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

Luego, cuando el usuario carga la página:

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

Luego, cuando el usuario navega:

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

Con esto guardo el token en la URL y mantengo el estado cuando el usuario está navegando. Perdí un poco de visibilidad de la URL, pero no hay una forma perfecta de hacerlo.

Por lo tanto, no habilite el modo HTML5 y luego agregue este controlador:

.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'' })