Angular 2 路由器事件侦听器
Angular 2 router event listener
如何在 Angular 2 路由器中监听状态变化?
在Angular1.x我使用了这个事件:
$rootScope.$on('$stateChangeStart',
function(event,toState,toParams,fromState,fromParams, options){ ... })
所以,如果我在 Angular 2:
中使用这个事件监听器
window.addEventListener("hashchange", () => {return console.log('ok')}, false);
不是return'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 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
。
另见
要监听所有状态更改,请扩展默认 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/
您可以使用 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...
}
});
angular 2 个路由器事件有不同的 classes,从 router.events
observable 传递给订阅的内容可以是 NavigationEnd
、NavigationCancel
、NavigationError
或 NavigationStart
。实际触发路由更新的将是 NavigationEnd
.
我会远离使用 instanceof
或 event.constructor.name
因为在 缩小 之后 class 名称将被破坏它无法正常工作.
您可以改用路由器的 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
}
)
in enableTracing true 在控制台中显示 routeEvents
在 enableTracing false 中隐藏 routeEvents in console
您还可以使用 filter()
.
过滤事件
但不要只是使用filter(e => e is NavigationEnd)
更好的解决方案是将 'type guard' 添加到 filter()
,如下所示:
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
它包含两件事:
e is NavigationEnd
这是您要为其定义函数的断言(这是打字稿语法,已完全从转译的 javascript 中删除)
e instanceof NavigationEnd
这是检查类型的实际运行时代码
这样做的好处是运算符进一步向下 'the pipe',例如下面的 map
现在知道类型是 NavigationEnd
,但是如果没有类型保护,您将有一个输入 Event
.
如果您只需要检查一种事件类型,那么这是最简洁的方法。这在严格模式下似乎也是必要的,以避免编译器错误。
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)
}
});
}
使用 @bespunky/angular-zen 这变得简单多了...
基本上,扩展 RouteAware
class 并创建一个 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}`);
}
}
看看这个答案:
直接来自 docs
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 错误。
如何在 Angular 2 路由器中监听状态变化?
在Angular1.x我使用了这个事件:
$rootScope.$on('$stateChangeStart',
function(event,toState,toParams,fromState,fromParams, options){ ... })
所以,如果我在 Angular 2:
中使用这个事件监听器window.addEventListener("hashchange", () => {return console.log('ok')}, false);
不是return'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 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
。
另见
要监听所有状态更改,请扩展默认 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/
您可以使用 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...
}
});
angular 2 个路由器事件有不同的 classes,从 router.events
observable 传递给订阅的内容可以是 NavigationEnd
、NavigationCancel
、NavigationError
或 NavigationStart
。实际触发路由更新的将是 NavigationEnd
.
我会远离使用 instanceof
或 event.constructor.name
因为在 缩小 之后 class 名称将被破坏它无法正常工作.
您可以改用路由器的 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
}
)
in enableTracing true 在控制台中显示 routeEvents 在 enableTracing false 中隐藏 routeEvents in console
您还可以使用 filter()
.
但不要只是使用filter(e => e is NavigationEnd)
更好的解决方案是将 'type guard' 添加到 filter()
,如下所示:
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
它包含两件事:
e is NavigationEnd
这是您要为其定义函数的断言(这是打字稿语法,已完全从转译的 javascript 中删除)e instanceof NavigationEnd
这是检查类型的实际运行时代码
这样做的好处是运算符进一步向下 'the pipe',例如下面的 map
现在知道类型是 NavigationEnd
,但是如果没有类型保护,您将有一个输入 Event
.
如果您只需要检查一种事件类型,那么这是最简洁的方法。这在严格模式下似乎也是必要的,以避免编译器错误。
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)
}
});
}
使用 @bespunky/angular-zen 这变得简单多了...
基本上,扩展 RouteAware
class 并创建一个 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}`);
}
}
看看这个答案:
直接来自 docs
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 错误。