首页 文章

Angular 2路由器事件监听器

提问于
浏览
55

如何在Angular 2路由器中监听状态变化?

在Angular 1.x中我使用了这个事件:

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

所以,如果我在Angular 2中使用这个eventlistener:

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()在服务中不起作用 .

我做错了什么?

6 回答

  • 0

    要收听所有状态更改,请扩展默认的RouterOutlet并在“activate”和“deactivate”处理程序中添加自己的逻辑 .

    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/

  • 121

    new router

    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

    对于新路由器,请不要忘记从 router 模块导入 NavigationStart

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

    因为如果你不导入它 instanceof 将无法正常工作,错误 NavigationStart is not defined 将会上升 .

    也可以看看

  • 3

    您可以使用 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...
      }
    });
    
  • -1

    您还可以使用 filter() 过滤事件 .

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

    一个更好的解决方案是添加'type guard'到这样的 filter()

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

    它包含两件事:

    • e is NavigationEnd 这是你为函数定义函数的断言(这是typescript语法)

    • e instanceof NavigationEnd 这是检查类型的实际运行时代码

    这样做的好处是运营商进一步向下'the pipe',如下面的 map 现在知道类型是 NavigationEnd ,但没有类型保护,你有一个类型 Event .

    如果您只需要检查一种事件类型,那么这是最干净的方法 . 在严格模式下,这似乎也是必要的,以避免编译器错误 .

    enter image description here

  • 4

    angular 2路由器事件具有不同的类,从 router.events observable传递给订阅的内容可以是 NavigationEndNavigationCancelNavigationErrorNavigationStart . 实际触发路由更新的那个将是 NavigationEnd .

    我会远离使用 instanceofevent.constructor.name ,因为在 minification 之后,类名将被破坏,它将无法正常工作 .

    您可以使用路由器的 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

    在angular2中,转到文件“app.modules.ts” - >导入

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

    在enableTracing中,在enableTracing中的控制台中显示true,显示routeEvent false在控制台中隐藏routeEvents

相关问题