[英]Angular 2 router event listener
How to listen state change in Angular 2 router? Angular 2路由器中如何监听state变化?
In Angular 1.x I used this event:在 Angular 1.x 中我使用了这个事件:
$rootScope.$on('$stateChangeStart',
function(event,toState,toParams,fromState,fromParams, options){ ... })
So, if I use this eventlistener in Angular 2:所以,如果我在 Angular 2 中使用这个事件监听器:
window.addEventListener("hashchange", () => {return console.log('ok')}, false);
it isn't return 'ok', then change state from JS, only then browser history.back() function run.它不返回“确定”,然后从 JS 更改 state,然后浏览器 history.back() function 运行。
Use router.subscribe() function as the service:使用 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');
})
}
}
Inject service in component which init in routing:在路由中初始化的组件中注入服务:
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) {}
}
I inject this service in other components such as in this example.我将此服务注入到其他组件中,例如本例中的组件。 Then I change state, console.info() in service not working.
然后我更改 state,console.info() in service not working。
What I do wrong?我做错了什么?
new router新路由器
constructor(router:Router) {
router.events.subscribe(event:Event => {
if(event instanceof NavigationStart) {
}
// NavigationEnd
// NavigationCancel
// NavigationError
// RoutesRecognized
});
}
old老的
Inject the Router and subscribe to route change events注入路由器并订阅路由变化事件
import {Router} from 'angular2/router';
class MyComponent {
constructor(router:Router) {
router.subscribe(...)
}
}
NOTE笔记
For the new router, don't forget to import NavigationStart
from router
module对于新的路由器,不要忘记从
router
模块中导入NavigationStart
import { Router, NavigationStart } from '@angular/router';
because if you don't import it instanceof
will not work and an error NavigationStart is not defined
will rise.因为如果你不导入它,
instanceof
将不起作用,并且NavigationStart is not defined
会出现错误。
See also也可以看看
You can also filter events with filter()
.您还可以使用
filter()
过滤事件。
But don't just use filter(e => e is NavigationEnd)
但不要只使用
filter(e => e is NavigationEnd)
A much better solution is to add a 'type guard' to filter()
like this:更好的解决方案是向
filter()
添加一个“类型保护”,如下所示:
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
It contains two things:它包含两件事:
e is NavigationEnd
this is the assertion you're defining a function for (this is typescript syntax and is completely stripped out of the transpiled javascript) e is NavigationEnd
这是您为其定义函数的断言(这是打字稿语法,完全从转译的 javascript 中剥离出来)e instanceof NavigationEnd
this is the actual runtime code that checks the type e instanceof NavigationEnd
这是检查类型的实际运行时代码The nice thing with this is that operators further down 'the pipe', like map
below now know the type is NavigationEnd
, but without the type-guard you'd have a type Event
.这样做的好处是操作员在“管道”下方,例如下面的
map
,现在知道类型是NavigationEnd
,但是如果没有类型保护,您将拥有类型Event
。
If you only need to check for one event type then this is the cleanest way to do so.如果您只需要检查一种事件类型,那么这是最简洁的方法。 This also appears to be necessary in strict mode to avoid compiler errors.
这在严格模式下似乎也是必要的,以避免编译器错误。
You can use instanceof
as @GünterZöchbauer answered您可以使用@GünterZöchbauer回答的
instanceof
this.router.events.subscribe(event => {
if(event instanceof NavigationStart) {
// do something...
}
}
or you can use a lazier approach, but remember constructor name can be changed easily while the function is still working!或者您可以使用更懒惰的方法,但请记住,在函数仍在工作时可以轻松更改构造函数名称!
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)
}
})
Although the docs give the code filter((e: Event)
but I changed this to filter((e: any)
or you get linting errors in WebStorm.尽管文档提供了代码
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)
}
});
}
The angular 2 router events has different classes, and what gets passed to the subscription from the router.events
observable can either be NavigationEnd
, NavigationCancel
, NavigationError
, or NavigationStart
. angular 2 路由器事件有不同的类,从
router.events
observable 传递给订阅的router.events
可以是NavigationEnd
、 NavigationCancel
、 NavigationError
或NavigationStart
。 The one that will actually trigger a routing update will be NavigationEnd
.真正触发路由更新的是
NavigationEnd
。
I would stay away from using instanceof
or event.constructor.name
because after minification the class names will get mangled it will not work correctly.我将远离使用
instanceof
或event.constructor.name
因为在缩小后类名将被破坏,它将无法正常工作。
You can use the router's isActive
function instead, shown here https://angular.io/docs/ts/latest/api/router/index/Router-class.html您可以改用路由器的
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
}
}
in angular2, go to file "app.modules.ts"->imports在 angular2 中,转到文件“app.modules.ts”->imports
RouterModule.forRoot(
appRoutes,
{
enableTracing: true
}
)
in enableTracing true show routeEvents in console in enableTracing false hide routeEvents in console在 enableTracing true 在控制台中显示 routeEvents 在 enableTracing false 在控制台中隐藏 routeEvents
With @bespunky/angular-zen this has become a lot simpler...有了@bespunky/angular-zen,这变得简单多了……
Basically, extend the RouteAware
class and create an on<EventType>()
method:基本上,扩展
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}`);
}
}
Take a look at this answer: https://stackoverflow.com/a/64864103/4371525看看这个答案: https : //stackoverflow.com/a/64864103/4371525
阅读有关Angular路由事件的博客,您将获得有关路由事件和调试的详细信息。
To listen to all state changes, extend the default RouterOutlet and add your own logic in 'activate' and 'deactivate' handlers.要侦听所有状态更改,请扩展默认 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!');
}
}
Copied from 'Custom Router Outlet' example here: https://auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in-depth/从此处复制的“自定义路由器插座”示例: https : //auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in-depth/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.