Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Вложенные маршруты и ленивая загрузка

Вложенный (дочерний) маршрут показывает компонент внутри другой страницы: на странице статьи под текстом открываются комментарии по адресу /posts/1/comments. Ленивая загрузка (lazy loading) — когда код страницы скачивается только при первом переходе на неё, и приложение открывается быстрее.

Дочерние маршруты

Сначала добавьте в PostApi метод для комментариев и тип PostComment (импортируйте его в сервис из ./post-comment):

// src/app/post-api.ts
getComments(postId: number) {
  return this.http.get<PostComment[]>(`${this.url}/${postId}/comments`);
}
// src/app/post-comment.ts
export interface PostComment {
  id: number;
  postId: number;
  name: string;
  email: string;
  body: string;
}

Создайте компонент ng generate component post-comments и опишите его как дочерний маршрут в свойстве children:

// src/app/app.routes.ts
export const routes: Routes = [
  { path: 'posts', component: PostList },
  {
    path: 'posts/:id',
    component: PostDetail,
    children: [{ path: 'comments', component: PostComments }],
  },
];

Второй router-outlet

Дочерний компонент выводится в <router-outlet /> внутри родителя. Добавьте его в шаблон статьи вместе со ссылкой:

<!-- src/app/post-detail/post-detail.html -->
@if (post(); as p) {
  <h2>{{ p.title }}</h2>
  <p>{{ p.body }}</p>
  <a routerLink="comments">Показать комментарии</a>
  <router-outlet />
}

Добавьте RouterOutlet в imports компонента PostDetail. Адрес без начального слеша в routerLink считается от текущей страницы: со страницы /posts/1 ссылка ведёт на /posts/1/comments.

Параметр родителя

Параметр id принадлежит родительскому маршруту, поэтому дочерний компонент берёт его у parent:

// src/app/post-comments/post-comments.ts
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { toSignal } from '@angular/core/rxjs-interop';
import { PostApi } from '../post-api';
 
@Component({
  selector: 'app-post-comments',
  template: `
    @for (c of comments(); track c.id) {
      <p><b>{{ c.email }}</b>: {{ c.body }}</p>
    }
  `,
})
export class PostComments {
  private id = Number(inject(ActivatedRoute).parent?.snapshot.paramMap.get('id'));
  comments = toSignal(inject(PostApi).getComments(this.id), { initialValue: [] });
}

Нажмите «Показать комментарии» — под статьёй появятся пять комментариев, а адрес станет /posts/1/comments.

Ленивая загрузка компонента

Вместо component укажите loadComponent — функцию с динамическим import():

// src/app/app.routes.ts
{
  path: 'todos',
  loadComponent: () => import('./todo-list/todo-list').then((m) => m.TodoList),
},

Уберите обычный import компонента TodoList в начале файла, иначе он всё равно попадёт в основной код. Команда ng serve покажет в терминале отдельный блок Lazy chunk files — это и есть код страницы, который скачается при переходе на /todos.

Ленивая группа маршрутов

Целый раздел с несколькими страницами выносят в свой файл маршрутов и подключают через loadChildren:

// src/app/admin/admin.routes.ts
import { Routes } from '@angular/router';
import { Dashboard } from './dashboard/dashboard';
 
export const adminRoutes: Routes = [
  { path: '', component: Dashboard },
];
// src/app/app.routes.ts
{
  path: 'admin',
  loadChildren: () => import('./admin/admin.routes').then((m) => m.adminRoutes),
},

Все страницы раздела /admin загрузятся одним куском при первом заходе.

Частая ошибка

Забыть <router-outlet /> в шаблоне родителя. Адрес меняется на /posts/1/comments, ошибок нет, но комментарии не появляются — дочернему компоненту некуда выводиться. Если у маршрута есть children, у его компонента должен быть свой router-outlet.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.