Angelitedocs ESEN

Inicio › Aprender

Router

Rutas con parámetros, anidadas, guards, resolvers, carga diferida y modos hash e history.

El router decide qué componente mostrar según la dirección. Se activa con provideRouter(rutas), y las pantallas se pintan donde pongas <router-outlet>. Los enlaces son <a routerLink="/ruta">. (No lo activo en esta página para no pisar sus anclas.)

Rutas, parámetros y anidación#

const { component, mount, provideRouter, router } = AngeLite;

class Home {}
component(Home, { template: `<h2>Inicio</h2>` });

// el padre tiene su propio outlet para las rutas hijas
class Admin {}
component(Admin, { template: `<nav>Administración</nav><router-outlet></router-outlet>` });
class AdminHome {} component(AdminHome, { template: `<h3>Resumen</h3>` });
class AdminUser { id = () => router.params().id; }
component(AdminUser, { template: `<h3>Usuario {{ id() }}</h3>` });

class NotFound {} component(NotFound, { template: `<h2>404</h2>` });

provideRouter([
  { path: '/', component: Home },
  { path: 'admin', component: Admin, children: [
    { path: '',          component: AdminHome },
    { path: 'users/:id', component: AdminUser }
  ] },
  { path: 'viejo', redirectTo: '/' },
  { path: '**',    component: NotFound }
]);

class App {}
component(App, {
  template: `
    <nav><a routerLink="/">Inicio</a> <a routerLink="/admin/users/42">Usuario 42</a></nav>
    <router-outlet></router-outlet>`
});
mount(App, document.getElementById('app'));
  • :id declara un parámetro; router.params() lo devuelve (ya decodificado) como objeto reactivo.
  • children anida rutas: el componente padre pinta a los hijos en su propio <router-outlet>, y no se reconstruye cuando solo cambia la ruta hija.
  • '' es la ruta índice de un padre; ** recoge todo lo demás; redirectTo reemplaza la entrada del historial.

Guards#

Una ruta puede declarar canActivate: [guard]. Un guard recibe { path, params, query, route } y devuelve true (pasar), false (quedarse donde estabas: la dirección se restaura) o una ruta (redirigir). Puede ser asíncrono; si el usuario navega a otra parte mientras espera, la navegación antigua se cancela.

const soloAdmin = async ({ path }) => (await sesion.esAdmin()) || '/login';

provideRouter([
  { path: 'admin', component: Admin, canActivate: [soloAdmin] },
  { path: 'login', component: Login }
]);

Datos antes de pintar: resolvers y query#

resolve: { usuario: ({ params }) => … } carga datos antes de mostrar la página; si falla, te quedas donde estabas y el error se registra. router.data().usuario los entrega. Los parámetros de consulta (?pagina=2) llegan en router.query() como { pagina: '2' }.

&#123; path: 'users/:id', component: User,
  resolve: &#123; user: ({ params }) => http.get('/users/' + params.id) &#125; &#125;

// en el componente:  router.data().user   ·   router.query().tab

Carga diferida de pantallas#

load: () => import('./pantalla.js') descarga el código de una ruta la primera vez que se visita (el módulo exporta el componente como default, o es el componente). Si la descarga falla, el error se registra y te quedas en la pantalla anterior.

&#123; path: 'informes', load: () => import('./informes.js') &#125;

Modos hash e history#

Por defecto el router usa el hash (#/ruta): funciona en cualquier hosting estático. Con provideRouter(rutas, { mode: 'history', base: '/app' }) usa rutas reales; entonces el servidor debe devolver la misma página para todas ellas. Los clics en routerLink navegan sin recargar (con Ctrl, Cmd, Mayús o target el navegador actúa como siempre), y una dirección compartida como /app#/ruta aterriza en /app/ruta.

Navegar desde el código

router.navigate('/ruta?x=1') añade una entrada al historial; router.navigate('/ruta', { replace: true }) sustituye la actual. En modo history una ruta como //otro-sitio nunca saca al usuario del sitio.