Как работают маршруты с параметрами (Route Parameters)?
В Angular маршруты с параметрами (Route Parameters) позволяют передавать данные в маршруты через URL-адрес. Это полезно для динамической навигации, например: просмотр страницы пользователя по его ID, открытие поста по slug, отображение деталей товара и т.д. Angular предоставляет инструменты для определения маршрутов с параметрами, извлечения их значений и реагирования на их изменения.
1. Определение маршрута с параметрами
В файле маршрутизации (app-routing.module.ts) параметры определяются с помощью двоеточия (:):
const routes: Routes = \[
{ path: 'user/:id', component: UserComponent },
{ path: 'post/:slug', component: PostComponent }
\];
В этом примере:
-
user/:id — параметр id динамический.
-
post/:slug — параметр slug динамический.
URL example.com/user/42 вызовет компонент UserComponent с параметром id = 42.
2. Навигация с параметрами
Маршруты с параметрами можно активировать двумя способами:
Через ссылку в шаблоне
<a \[routerLink\]="\['/user', user.id\]">Профиль</a>
Это навигация к маршруту user/123, если user.id = 123.
Через Router программно
constructor(private router: Router) {}
goToUserProfile(id: number) {
this.router.navigate(\['/user', id\]);
}
3. Получение параметров в компоненте
Angular предоставляет два основных способа получения параметров маршрута:
Через ActivatedRoute.snapshot
Если параметры не будут меняться после инициализации компонента (например, при первой загрузке), можно использовать snapshot:
constructor(private route: ActivatedRoute) {}
ngOnInit() {
const userId = this.route.snapshot.paramMap.get('id');
}
paramMap.get('id') возвращает значение параметра id в виде строки (или null).
Через ActivatedRoute.params (Observable)
Если маршрут может измениться, пока компонент жив (например, если он не уничтожается при переходе на другую страницу с другим параметром), нужно подписаться на params:
this.route.params.subscribe(params => {
const id = params\['id'\];
});
Важно отписываться от этой подписки при уничтожении компонента, чтобы избежать утечек памяти.
Пример с ngOnDestroy:
subscription!: Subscription;
ngOnInit() {
this.subscription = this.route.params.subscribe(params => {
this.userId = params\['id'\];
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
4. Несколько параметров в маршруте
Можно указать несколько параметров:
{ path: 'category/:categoryId/product/:productId', component: ProductComponent }
Путь category/12/product/55 создаст:
-
categoryId = 12
-
productId = 55
Получение в компоненте:
this.route.params.subscribe(params => {
const categoryId = params\['categoryId'\];
const productId = params\['productId'\];
});
5. Query Parameters (параметры запроса)
Это параметры, добавляемые к URL после ?, не входящие в путь маршрута:
Пример URL: /products?page=2&sort=asc
Чтение:
this.route.queryParamMap.subscribe(queryParams => {
const page = queryParams.get('page');
const sort = queryParams.get('sort');
});
Программная установка:
this.router.navigate(\['/products'\], { queryParams: { page: 2, sort: 'asc' } });
6. Обработка изменений параметров маршрута
Если пользователь переходит с /user/1 на /user/2, Angular может не пересоздать компонент UserComponent (если он уже активен), а просто изменит параметры. Поэтому следует всегда подписываться на params, чтобы реагировать на изменения.
this.route.params.subscribe(params => {
this.loadUser(params\['id'\]);
});
7. Использование ActivatedRoute в дочерних маршрутах
Если компонент вложен и параметры задаются на уровне родителя:
const routes: Routes = \[
{
path: 'user/:id',
component: UserComponent,
children: \[
{ path: 'profile', component: ProfileComponent }
\]
}
\];
Чтобы получить параметр id в дочернем компоненте (ProfileComponent), используйте parent:
this.route.parent?.params.subscribe(params => {
const userId = params\['id'\];
});
8. Route Resolvers (предзагрузка данных)
Если нужно получить данные по параметру до активации компонента, используйте resolve.
{
path: 'user/:id',
component: UserComponent,
resolve: {
user: UserResolver
}
}
Реализация UserResolver:
@Injectable({ providedIn: 'root' })
export class UserResolver implements Resolve<User> {
constructor(private userService: UserService) {}
resolve(route: ActivatedRouteSnapshot): Observable<User> {
const id = route.paramMap.get('id')!;
return this.userService.getUserById(+id);
}
}
В компоненте доступ к данным:
ngOnInit() {
this.route.data.subscribe(data => {
this.user = data\['user'\];
});
}
9. Пример полного цикла
Роутинг:
{ path: 'order/:orderId', component: OrderDetailComponent }
Шаблон:
<a \[routerLink\]="\['/order', order.id\]">Посмотреть заказ</a>
Компонент:
export class OrderDetailComponent implements OnInit {
orderId!: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.params.subscribe(params => {
this.orderId = params\['orderId'\];
this.fetchOrderDetails();
});
}
fetchOrderDetails() {
// Запрос на сервер по orderId
}
}
Параметры маршрута — мощный механизм, позволяющий динамически управлять навигацией и данными в Angular-приложениях. Они обеспечивают простую интеграцию с URL, что важно как для UX, так и для SEO.