web-dev-qa-db-ja.com

Angular 2ルーターイベントリスナー

Angular 2ルーターで状態の変化をリッスンする方法は?

Angular 1.xでは、このイベントを使用しました。

$rootScope.$on('$stateChangeStart',
    function(event,toState,toParams,fromState,fromParams, options){ ... })

したがって、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()が機能しません。

私が間違っていることは何ですか?

58
Egor Medvedev

新しいルーター

constructor(router:Router) {
  router.events.subscribe(event:Event => {
    if(event instanceof NavigationStart) {
    }
    // NavigationEnd
    // NavigationCancel
    // NavigationError
    // RoutesRecognized
  });
}

old

ルーターを挿入し、ルート変更イベントにサブスクライブします

import {Router} from 'angular2/router';

class MyComponent {
  constructor(router:Router) {
    router.subscribe(...)
  }
}

NOTE

新しいルーターの場合は、NavigationStartモジュールからrouterをインポートすることを忘れないでください

import { Router, NavigationStart } from '@angular/router';

インポートしないとinstanceofが機能せず、エラーNavigationStart is not definedが発生するためです。

こちらもご覧ください

124

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...
  }
});
4

filter()を使用してイベントをフィルタリングすることもできます。

しかし、justfilter(e => e is NavigationEnd)を使用しないでください

より良い解決策は、次のようにfilter()に 'type guard'を追加することです:

 filter((e): e is NavigationEnd => e instanceof NavigationEnd), 

次の2つが含まれます。

  • e is NavigationEndこれは関数を定義しているアサーションです(これはTypeScript構文です)
  • e instanceof NavigationEndこれは、型をチェックする実際の実行時コードです

これの良い点は、以下のmapのように、演算子が「パイプ」のさらに下にあることで、タイプがNavigationEndであることを知っていますが、タイプガードなしではタイプEventになります。

1つのイベントタイプのみをチェックする必要がある場合、これが最もクリーンな方法です。これは、コンパイラエラーを回避するために、厳格モードでも必要であると思われます。

enter image description here

3
Simon_Weaver

angular2で、ファイル「app.modules.ts」-> importsに移動します

RouterModule.forRoot(
      appRoutes,
      { 
         enableTracing: true
      }
)

enableTracingでtrueコンソールでrouteEventsを表示enableTracingでfalse falseコンソールでrouteEventsを非表示

angular 2ルーターイベントにはさまざまなクラスがあり、router.eventsオブザーバブルからサブスクリプションに渡されるものは、NavigationEndNavigationCancelNavigationError、またはNavigationStartのいずれかです。実際にルーティング更新をトリガーするのは、NavigationEndです。

minificationの後、クラス名が壊れて正しく動作しないため、instanceofまたはevent.constructor.nameの使用を避けます。

ここに示すように、代わりにルーターの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
  }
}
0
Y. Brahimi