Angular 2 路由器事件监听器

IT技术 javascript angular typescript angular2-routing
2021-01-17 01:01:33

如何监听 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() in service 不工作。

我做错了什么?

6个回答

新路由器

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

笔记

对于新的路由器,不要忘记NavigationStartroutermodule导入

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

因为如果你不导入它就instanceof不会工作并且错误NavigationStart is not defined会增加。

也可以看看

我需要router.subscribe(...)在每节课上都跑还是我可以跑一次?在文档中,我不明白必须在订阅功能中输入哪些参数?你能写完整的例子吗?
2021-03-19 01:01:33
您能否编辑您的问题并添加演示您尝试完成的操作的代码?我不知道您将服务注入到何处或如何进行。
2021-03-23 01:01:33
如果我将它作为服务注入到其他组件中,它不会返回任何数据
2021-03-29 01:01:33
@LazarLjubenović 人们经常找到旧示例,然后遇到问题,因为代码不再起作用。我认为对他们来说,看到这是因为 Angular 发生了变化,并且该示例适用于较旧的 Angular 版本,这对他们很有帮助。没有其他方法可以了解这一点,因为旧文档不再可用。
2021-04-04 01:01:33
您可以在全局服务中执行一次,然后在您想要访问的任何地方注入该服务。
2021-04-05 01:01:33

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

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

一个更好的解决方案是filter()像这样添加一个“类型保护”

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

它包含两件事:

  • e is NavigationEnd 这是您为其定义函数的断言(这是typescript语法,完全从转译的 javascript 中剥离出来)
  • e instanceof NavigationEnd 这是检查类型的实际运行时代码

这样做的好处是操作员在“管道”map下方,如下所示,现在知道类型是NavigationEnd,但是如果没有类型保护,您将拥有类型Event

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

在此处输入图片说明

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

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

或者您可以使用更懒惰的方法,但请记住,在函数仍在工作时可以轻松更改构造函数名称!

this.router.events.subscribe(event => {
  if(event.constructor.name === "NavigationStart") {
    // do something...
  }
});
这是一种非常不安全的方法,应该强烈劝阻。
2021-03-22 01:01:33
这种方法对缩小也很脆弱,因为可以更改构造函数名称,例如event.constructor.name可能是'A'
2021-04-09 01:01:33
您不想使用的考虑因素是什么instanceof
2021-04-12 01:01:33
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)
    }
  });
}

角2个路由器事件有不同的类别,什么被传递到订阅从router.events观察到的可以是NavigationEndNavigationCancelNavigationError,或NavigationStart真正触发路由更新的将是NavigationEnd.

我会远离使用,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
  }
}