1. Знакомство с <router-outlet>
Если маршруты — это карта, по которой Angular определяет, какой компонент показать для каждого URL, то <router-outlet> — это «окно», в которое Angular подгружает нужный компонент. Можно сказать, что <router-outlet> — это телепорт для ваших компонентов: куда Angular «приземляет» компонент, соответствующий текущему маршруту.
Аналогия:
Представьте себе многоэтажный дом, где в каждой квартире живёт свой компонент. <router-outlet> — это дверь, через которую в квартиру входит тот, кто соответствует текущему адресу (URL). Если адрес изменился — Angular «выгоняет» одного жильца и заводит нового.
Без <router-outlet> Angular просто не знает, куда вставлять компоненты маршрутов! Даже если маршруты настроены идеально, если в шаблоне нет <router-outlet>, компоненты маршрутов не появятся на экране.
Как работает <router-outlet>
Когда Angular стартует приложение, он ищет в шаблоне компонент, куда он может «вставить» компонент маршрута. Обычно <router-outlet> располагают в корневом компоненте приложения (AppComponent). Когда пользователь переходит по ссылке или меняется URL, Angular:
- Сравнивает URL с определёнными маршрутами.
- Находит компонент, который должен быть отображён.
- Вставляет этот компонент внутрь <router-outlet>.
Схема работы:
flowchart TD
A[Маршрут: /about] --> B[Компонент AboutComponent]
B --> C[<router-outlet> в шаблоне]
C --> D[Отображение на странице]
2. Практический пример: базовое приложение с маршрутизацией
Шаг 1. Настроим маршруты
Допустим, у нас есть два компонента: HomeComponent и AboutComponent. Мы хотим показывать их на разных маршрутах:
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
const routes: Routes = [
{ path: '', component: HomeComponent }, // Главная страница
{ path: 'about', component: AboutComponent } // О нас
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Шаг 2. Используем <router-outlet> в шаблоне
В app.component.html (или любом другом компоненте, где вы хотите отображать маршруты):
<!-- app.component.html -->
<h1>Моё Angular-приложение</h1>
<nav>
<a routerLink="/">Главная</a> |
<a routerLink="/about">О нас</a>
</nav>
<hr>
<router-outlet></router-outlet>
Что происходит:
— При переходе по ссылке «Главная» (/), в <router-outlet> появится содержимое HomeComponent.
— При переходе по «О нас» (/about), в <router-outlet> появится AboutComponent.
Шаг 3. Примеры компонентов
// home.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
template: `<h2>Добро пожаловать на главную!</h2>`
})
export class HomeComponent { }
// about.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-about',
template: `<h2>О нас: мы любим Angular!</h2>`
})
export class AboutComponent { }
Результат:
В зависимости от активного маршрута в <router-outlet> будет отображаться соответствующий компонент.
3. Можно ли использовать несколько <router-outlet>?
Да, и это не баг, а фича! В Angular можно вставлять несколько <router-outlet> в разные части шаблона. Это используется для вложенных маршрутов (child routes) и для параллельных маршрутов. Но если вы только начинаете, не спешите усложнять жизнь — один <router-outlet> в корневом компоненте покрывает 99% задач новичка.
Пример вложенных маршрутов:
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent, children: [
{ path: 'team', component: TeamComponent }
]
}
];
В шаблоне AboutComponent:
<!-- about.component.html -->
<h2>О нас</h2>
<router-outlet></router-outlet> <!-- Здесь появится TeamComponent при маршруте /about/team -->
4. Полезные нюансы
Как Angular решает, куда вставлять компонент?
Angular всегда ищет ближайший подходящий <router-outlet>, начиная с корневого компонента. Если маршрут простой (без вложенности), то компонент попадёт в <router-outlet> в AppComponent. Если маршрут вложенный, то дочерний компонент попадёт в <router-outlet> внутри родительского компонента.
graph TD
A[AppComponent] -->|<router-outlet>| B[AboutComponent]
B -->|<router-outlet>| C[TeamComponent]
Советы по размещению <router-outlet>
- Обычно размещайте <router-outlet> там, где должен меняться основной контент страницы.
- Всё, что написано до/после <router-outlet>, будет всегда видно (например, меню, футер).
- Можно стилизовать <router-outlet> через обёртку, если нужно добавить отступы, фон и пр.
Пример:
<header>Меню</header>
<main>
<router-outlet></router-outlet>
</main>
<footer>Подвал</footer>
Как работает <router-outlet> за кулисами
Если вы любите смотреть под капот, знайте: <router-outlet> — это Angular-директива, которая слушает сервис маршрутизации и динамически создает нужный компонент, когда меняется маршрут. Angular не просто вставляет HTML, а реально создаёт экземпляр компонента, с жизненным циклом, зависимостями и т.д.
5. Интерактивная практика: добавим третий маршрут
Давайте добавим страницу «Контакты» и убедимся, что всё работает.
- Создайте компонент:
ng generate component contacts - Добавьте маршрут:
// app-routing.module.ts { path: 'contacts', component: ContactsComponent } - Добавьте ссылку в меню:
<a routerLink="/contacts">Контакты</a> - В шаблоне компонента:
<!-- contacts.component.html --> <h2>Свяжитесь с нами!</h2> <p>Email: hello@example.com</p>
Теперь при переходе по /contacts в <router-outlet> появится ContactsComponent.
Магия? Нет, просто Angular и <router-outlet>!
6. Типичные ошибки при работе с <router-outlet>
Ошибка №1: Забыли добавить <router-outlet> в шаблон.
Самая частая проблема. Вы настроили маршруты, переходите по ссылкам — а на экране ничего не меняется. Почему? Потому что Angular не знает, куда вставлять компонент маршрута. Добавьте <router-outlet> — и всё заработает.
Ошибка №2: Несколько <router-outlet>, но маршруты не вложенные.
Если у вас несколько <router-outlet>, но маршруты не вложены или не настроены правильно, Angular не сможет понять, какой компонент куда вставлять. В результате — пустые места или неожиданные ошибки.
Ошибка №3: Путают <router-outlet> с селекторами компонентов.
Иногда новички пытаются вставить компонент маршрута через его селектор (<app-home></app-home>), а не через <router-outlet>. Это не будет работать с маршрутизацией — компонент просто всегда будет на странице, независимо от маршрута.
Ошибка №4: Нет импорта RouterModule
Если забыли импортировать RouterModule в модуль, где используете <router-outlet>, получите ошибку «Can't bind to 'routerLink' since it isn't a known property» или «'router-outlet' is not a known element». Проверьте импорты!
Ошибка №5: Стилизация <router-outlet>
Иногда пытаются стилизовать сам <router-outlet>, забывая, что это не визуальный элемент, а директива. Стилизовать нужно обёртку вокруг него.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ