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/