По умолчанию маршрутизатор Angular 2 использует компоненты повторно, если текущий и будущий маршруты совпадают. В этом посте показано, как эта стратегия влияет на реализацию компонента и как эту стратегию можно изменить.
Устаревший компонент
Вот пример компонента, который показывает устаревшие данные. Когда маршрут приложения изменяется с «/ detail / 1» на «/ detail / 2», компонент DetailStaleComponent по-прежнему показывает начальный параметр 1.
import { Component, OnInit } from '@angular/core'; import {ActivatedRoute} from '@angular/router'; @Component({ selector: 'app-detail-stale', template: '<p>detail stale for {{id}} param</p>' }) export class DetailStaleComponent implements OnInit { id: string; constructor(private route: ActivatedRoute) { } ngOnInit() { this.id = this.route.snapshot.params['id']; } }
Подпишитесь на изменения
Компонент должен подписаться на изменения параметров маршрута и обновлять свою модель / представление, когда маршрут приложения изменяется с «/ detail / 1» на «/ detail / 2». Метод компонента ngOnInit получает доступ к наблюдаемым параметрам ActivatedRoute и использует асинхронный конвейер для поддержания параметра в актуальном состоянии.
import {Component, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/pluck'; @Component({ selector: 'app-detail-reusable', template: `<p>detail reusable for {{id$| async}} param </p>` }) export class DetailReusableComponent implements OnInit { id$: Observable<string>; constructor(private route: ActivatedRoute) { } ngOnInit() { this.id$ = this.route.params.pluck('id'); } }
RouteReuseStrategy
Маршрут Angular 2 позволяет изменить стратегию повторного использования по умолчанию. В этом примере показано, как настраиваемый RouteReuseStrategy помогает устранить устаревшие данные в ситуации, когда компонент не использует подписку.
Angular 2 использует DefaultRouteReuseStrategy, если приложение не предоставляет настраиваемую. DefaultRouteReuseStrategy реализует интерфейс RouteReuseStrategy, который определяет метод shouldReuseRoute, который используется маршрутизатором для принятия решения о повторном использовании.
export abstract class RouteReuseStrategy { /** Determines if this route (and its subtree) should be detached to be reused later */ abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; /** Stores the detached route */ abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void; /** Determines if this route (and its subtree) should be reattached */ abstract shouldAttach(route: ActivatedRouteSnapshot): boolean; /** Retrieves the previously stored route */ abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle; /** Determines if a route should be reused */ abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; }
Давайте определим нашу собственную CustomRouteReuseStrategy, которая не позволяет повторно использовать наш компонент DetailSameComponent. Компонент DetailSameComponent идентичен компоненту DetailStaleComponent, определенному выше.
import {DefaultRouteReuseStrategy} from '@angular/router/src/router'; import {ActivatedRouteSnapshot} from '@angular/router'; export class CustomRouteReuseStrategy extends DefaultRouteReuseStrategy { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { let name = future.component && (<any>future.component).name; return super.shouldReuseRoute(future, curr) && name !== 'DetailSameComponent'; } }
Стратегия - это сервис Angular 2, который должен быть зарегистрирован в модуле.
@NgModule({ declarations: [AppComponent, ListComponent, DetailReusableComponent, DetailStaleComponent, DetailSameComponent], imports: [BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(routes)], providers: [ { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } ], bootstrap: [AppComponent] }) export class AppModule { }
И вот результат - компонент показывает правильные данные после изменения маршрута с «/ detail / 1» на «/ detail / 2».
Вот ссылка на репозиторий github angular2-router-reuse, содержащий полный код.