簡體   English   中英

Angular 2 路由器事件監聽器

[英]Angular 2 router event listener

Angular 2路由器中如何監聽state變化?

在 Angular 1.x 中我使用了這個事件:

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

所以,如果我在 Angular 2 中使用這個事件監聽器:

window.addEventListener("hashchange", () => {return console.log('ok')}, false);

它不返回“確定”,然后從 JS 更改 state,然后瀏覽器 history.back() function 運行。

使用 router.subscribe() function 作為服務:

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) {}
}

我將此服務注入到其他組件中,例如本例中的組件。 然后我更改 state,console.info() in service not working。

我做錯了什么?

新路由器

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(...)
  }
}

筆記

對於新的路由器,不要忘記從router模塊中導入NavigationStart

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

因為如果你不導入它, instanceof將不起作用,並且NavigationStart is not defined會出現錯誤。

也可以看看

您還可以使用filter()過濾事件。

但不要使用filter(e => e is NavigationEnd)

更好的解決方案是向filter()添加一個“類型保護”,如下所示:

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

它包含兩件事:

  • e is NavigationEnd這是您為其定義函數的斷言(這是打字稿語法,完全從轉譯的 javascript 中剝離出來)
  • e instanceof NavigationEnd這是檢查類型的實際運行時代碼

這樣做的好處是操作員在“管道”下方,例如下面的map ,現在知道類型是NavigationEnd ,但是如果沒有類型保護,您將擁有類型Event

如果您只需要檢查一種事件類型,那么這是最簡潔的方法。 這在嚴格模式下似乎也是必要的,以避免編譯器錯誤。

在此處輸入圖片說明

您可以使用@GünterZöchbauer回答的instanceof

this.router.events.subscribe(event => {
  if(event instanceof NavigationStart) {
    // do something...
  }
}

或者您可以使用更懶惰的方法,但請記住,在函數仍在工作時可以輕松更改構造函數名稱!

this.router.events.subscribe(event => {
  if(event.constructor.name === "NavigationStart") {
    // do something...
  }
});

直接來自文檔

import {Event, RouterEvent, Router, NavigationEnd} from '@angular/router';

this.router.events.pipe(
  filter((e: any): e is RouterEvent => e instanceof RouterEvent)
).subscribe((evt: RouterEvent) => {
  if (evt instanceof NavigationEnd) {
    console.log(evt.url)
  }
})

盡管文檔提供了代碼filter((e: Event)但我將其更改為filter((e: any)否則您會在 WebStorm 中遇到 linting 錯誤。

import { Router,NavigationEnd  } from '@angular/router';
constructor(private route:Router){

  this.routeEvent(this.route);

}
routeEvent(router: Router){
  router.events.subscribe(e => {
    if(e instanceof NavigationEnd){
      console.log(e)
    }
  });
}

angular 2 路由器事件有不同的類,從router.events observable 傳遞給訂閱的router.events可以是NavigationEndNavigationCancelNavigationErrorNavigationStart 真正觸發路由更新的是NavigationEnd

我將遠離使用instanceofevent.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
  }
}

在 angular2 中,轉到文件“app.modules.ts”->imports

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

在 enableTracing true 在控制台中顯示 routeEvents 在 enableTracing false 在控制台中隱藏 routeEvents

有了@bespunky/angular-zen,這變得簡單多了……

基本上,擴展RouteAware類並創建一個on<EventType>()方法:

import { Component                                        } from '@angular/core';
import { NavigationStart, NavigationEnd, RoutesRecognized } from '@angular/router';
import { RouteAware                                       } from '@bespunky/angular-zen/router-x';

@Component({
    selector   : 'app-demo',
    templateUrl: './demo.component.html',
    styleUrls  : ['./demo.component.css']
})
export class DemoComponent extends RouteAware
{
    // ✨ Any router event can have a handler method.
    // See https://angular.io/guide/router#router-events for a complete list of angular's router events.

    // ✨ Use `this.router` to access the router
    // ✨ Use `this.route` to access the activated route
    // ✨ Use `this.componentBus` to access the RouterOutletComponentBus service
    
    protected onNavigationStart(event: NavigationStart): void
    {
        console.log(`Navigation started for: ${event.url}`);
    }

    protected onRoutesRecognized(event: RoutesRecognized): void
    {
        console.log('Recognized routes.');
    }
    
    protected onNavigationEnd(event: NavigationEnd): void
    {
        console.log(`Navigation ended for: ${event.url}`);
    }
}

看看這個答案: https : //stackoverflow.com/a/64864103/4371525

閱讀有關Angular路由事件的博客,您將獲得有關路由事件和調試的詳細信息。

要偵聽所有狀態更改,請擴展默認 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!');
  }
}

從此處復制的“自定義路由器插座”示例: https : //auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in-depth/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM