Angular 2 прослушивателя событий маршрутизатора
Как прослушивать изменение состояния в маршрутизаторе Angular 2?
В Angular 1.x я использовал это событие:
$rootScope.$on('$stateChangeStart',
function(event,toState,toParams,fromState,fromParams, options){ ... })
Итак, если я использую этот eventlistener в Angular 2:
window.addEventListener("hashchange", () => {return console.log('ok')}, false);
он не возвращает "ok", а затем меняет состояние из JS, запускается только функция history.back() браузера.
В качестве службы используйте функцию router.subscribe():
import {Injectable} from 'angular2/core';
import {Router} from 'angular2/router';
@Injectable()
export class SubscribeService {
constructor (private _router: Router) {
this._router.subscribe(val => {
console.info(val, '<-- subscribe func');
})
}
}
Ввести услугу в компоненте, который инициализируется при маршрутизации:
import {Component} from 'angular2/core';
import {Router} from 'angular2/router';
@Component({
selector: 'main',
templateUrl: '../templates/main.html',
providers: [SubscribeService]
})
export class MainComponent {
constructor (private subscribeService: SubscribeService) {}
}
Я внедряю эту службу в другие компоненты, такие как в этом примере. Затем я меняю состояние, console.info() в службе не работает.
Что я делаю неправильно?
Ответы
Ответ 1
новый маршрутизатор
constructor(router:Router) {
router.events.subscribe(event:Event => {
if(event instanceof NavigationStart) {
}
// NavigationEnd
// NavigationCancel
// NavigationError
// RoutesRecognized
});
}
старый
Ввести маршрутизатор и подписаться на события изменения маршрута
import {Router} from 'angular2/router';
class MyComponent {
constructor(router:Router) {
router.subscribe(...)
}
}
Примечание
Для нового маршрутизатора не забудьте импортировать NavigationStart
из router
module
import { Router, NavigationStart } from '@angular/router';
потому что, если вы его не импортируете, instanceof
не будет работать, а ошибка NavigationStart is not defined
повысится.
См. также
Ответ 2
Вы можете использовать instanceof
для ответа @GünterZöchbauer
this.router.events.subscribe(event => {
if(event instanceof NavigationStart) {
// do something...
}
}
или вы можете использовать подход lazier, но помните, что имя конструктора можно легко изменить, пока функция все еще работает!
this.router.events.subscribe(event => {
if(event.constructor.name === "NavigationStart") {
// do something...
}
});
Ответ 3
События маршрутизатора angular 2 имеют разные классы, и то, что передается подписке от наблюдаемого router.events
, может быть NavigationEnd
, NavigationCancel
, NavigationError
или NavigationStart
. Тот, который фактически инициирует обновление маршрутизации, будет NavigationEnd
.
Я бы держался подальше от использования instanceof
или event.constructor.name
, потому что после minification имена классов будут искажены, они не будут работать правильно.
Вместо этого вы можете использовать функцию router isActive
, показанную здесь https://angular.io/docs/ts/latest/api/router/index/Router-class.html
this.routerEventSubscription = this._router.events.subscribe((event: any) => {
if (this._router.isActive(events.url, false)) {
// true if the url route is active
}
}
Ответ 4
в angular2, перейдите в файл "app.modules.ts" → import
RouterModule.forRoot(
appRoutes,
{
enableTracing: true
}
)
в enableTracing true show routeEvents в консоли
в enableTracing false hide routeEvents в консоли
Ответ 5
Вы также можете фильтровать события с помощью filter()
.
Но не делайте filter(e => e is NavigationEnd)
!!!
Гораздо лучшим решением является добавление 'type guard' в filter()
:
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
Он содержит две вещи:
-
e is NavigationEnd
это утверждение, для которого вы определяете функцию (это синтаксис машинописи) -
e instanceof NavigationEnd
это фактический код времени выполнения, который проверяет тип
Приятно то, что операторы, расположенные ниже по "трубе", как и map
ниже, теперь знают, что типом является NavigationEnd
, но без защитника типа у вас будет тип Event
.
Если вам нужно проверить только один тип события, это самый чистый способ сделать это. Это также необходимо в строгом режиме, чтобы избежать ошибок компиляции.
![enter image description here]()
Ответ 6
Чтобы прослушать все изменения состояния, расширьте RouterOutlet по умолчанию и добавьте свою собственную логику в обработчики "активировать" и "деактивировать".
import {Directive} from 'angular2/core';
import {Router, RouterOutlet, ComponentInstruction} from 'angular2/router';
@Directive({
selector: 'router-outlet'
})
export class MyOwnRouterOutlet extends RouterOutlet {
...
activate() {
console.log('Hello from the new router outlet!');
}
}
Скопировано из примера "Custom Router Outlet" здесь: https://auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in-depth/