如何检测Angular中的路由变化?

Ang*_*arM 352 angular

我期待检测我的路线变化AppComponent.

此后,我将检查全局用户令牌以查看他是否已登录.然后,如果用户未登录,我可以重定向用户.

Lud*_*hen 442

在Angular 2中,您可以subscribe(Rx事件)到Router实例.所以你可以做的事情

class MyClass {
  constructor(private router: Router) {
    router.subscribe((val) => /*whatever*/)
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑(自rc.1起)

class MyClass {
  constructor(private router: Router) {
    router.changes.subscribe((val) => /*whatever*/)
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑2(自2.0.0起)

另见:Router.events doc

class MyClass {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
        // see also 
        console.log(val instanceof NavigationEnd) 
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 它为什么会发射3次? (7认同)
  • @Akshay你看过Todd Motto的这篇文章:[Angular 2中带路由器事件的动态页面标题](https://toddmotto.com/dynamic-page-titles-angular-2-router-events) (5认同)
  • 您可以使用RxJS`filter`运算符轻松过滤事件。`router.events.pipe(filter(e => e instanceof NavigationEnd).subscribe((e)=> {...}`) (5认同)
  • 我能够通过`event._root.children [0] .value._routeConfig.data获取数据.我希望有更好的方法 (2认同)
  • @Toolkit是因为事件具有3个状态并且成功更改了url。这三个状态是:“ NavigationStart”,“ NavigationEnd”和“ RoutesRecognized” (2认同)
  • 你可以检查 `if (val instanceof NavigationStart)` 让它触发一次 (2认同)
  • @Simon_Weaver 我不确定,但我认为你忘记了 ``.subscribe(``` 之前的右括号 (2认同)

Gün*_*uer 288

RxJS 6

router.events.pipe(filter(event => event instanceof NavigationStart))
Run Code Online (Sandbox Code Playgroud)

感谢Peilonrayz(见下面的评论)

新路由器> = RC.3

import { Router, NavigationStart, NavigationEnd, NavigationError, NavigationCancel, RoutesRecognized } from '@angular/router';

constructor(router:Router) {
  router.events.forEach((event) => {
    if(event instanceof NavigationStart) {
    }
    // NavigationEnd
    // NavigationCancel
    // NavigationError
    // RoutesRecognized
  });
}
Run Code Online (Sandbox Code Playgroud)

您还可以按给定的事件进行过滤:

import 'rxjs/add/operator/filter';

constructor(router:Router) {
  router.events
    .filter(event => event instanceof NavigationStart)
    .subscribe((event:NavigationStart) => {
      // You only receive NavigationStart events
    });
}
Run Code Online (Sandbox Code Playgroud)

使用pairwise运算符来获取先前和当前事件也是一个不错的主意.https://github.com/angular/angular/issues/11268#issuecomment-244601977

import 'rxjs/add/operator/pairwise';
import { Router } from '@angular/router;

export class AppComponent {
    constructor(private router: Router) {
        this.router.events.pairwise().subscribe((event) => {
            console.log(event);
        });
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 这确实会在当前版本上抛出一个编译错误```类型的参数'(event:Event)=> void'不能赋值给```的参数 (2认同)
  • 第二个示例应该是 NavigationEvent 而不是 Event。也不要忘记从@angular/router 导入“Event as NavigationEvent” (2认同)

小智 65

对于Angular 7,有人应该这样写:

this.router.events.subscribe((event: Event) => {})


一个详细的例子如下:

import { Component } from '@angular/core'; 
import { Router, Event, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`
})
export class AppComponent {

    constructor(private router: Router) {

        this.router.events.subscribe((event: Event) => {
            if (event instanceof NavigationStart) {
                // Show loading indicator
            }

            if (event instanceof NavigationEnd) {
                // Hide loading indicator
            }

            if (event instanceof NavigationError) {
                // Hide loading indicator

                // Present error to user
                console.log(event.error);
            }
        });

   }
}
Run Code Online (Sandbox Code Playgroud)

  • 在** constructor **中,您不应使用&lt;this&gt;,您的情况适用于ngOnInit。 (4认同)
  • 这很棒!很全面!在Angular 7上完美工作。 (2认同)
  • 该解决方案不受组件限制,它遍布整个应用程序,消耗资源 (2认同)

Dru*_*lan 39

角6,如果你要subscriberouter

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

import { filter } from 'rxjs/operators';

constructor(
  private router: Router
) {
  router.events.pipe(
    filter(event => event instanceof NavigationEnd)  
  ).subscribe((event: NavigationEnd) => {
    console.log(event.url);
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 它不捕获重定向事件 (4认同)
  • @AnandhuAjayakumar 当然可以!该事件有两个属性“url”和“urlAfterRedirects”,在重定向的情况下,该事件将“url”设置为进行重定向的路径,并将“urlAfterRedirects”设置为重定向后的路径 (2认同)

Ara*_*ind 36

Angular 4.x及以上:

这可以使用ActivatedRoute类的url属性来实现,如下所示,

this.activatedRoute.url.subscribe(url =>{
     console.log(url);
});
Run Code Online (Sandbox Code Playgroud)

注意: 您需要从angular/router包中导入和注入提供程序

import { ActivatedRoute } from '@angular/router`
Run Code Online (Sandbox Code Playgroud)

constructor(private activatedRoute : ActivatedRoute){  }
Run Code Online (Sandbox Code Playgroud)


Roh*_*007 31

在 Angular 8 中,你应该这样做 this.router.events.subscribe((event: Event) => {})

例子:

import { Component } from '@angular/core'; 
import { Router, Event } from '@angular/router';
import { NavigationStart, NavigationError, NavigationEnd } from '@angular/router';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`
})
export class AppComponent {

    constructor(private router: Router) {
        //Router subscriber
        this.router.events.subscribe((event: Event) => {
            if (event instanceof NavigationStart) {
                //do something on start activity
            }

            if (event instanceof NavigationError) {
                // Handle error
                console.error(event.error);
            }

            if (event instanceof NavigationEnd) {
                //do something on end activity
            }
        });
   }
}
Run Code Online (Sandbox Code Playgroud)


小智 16

路由器3.0.0-beta.2应该是

this.router.events.subscribe(path => {
  console.log('path = ', path);
});
Run Code Online (Sandbox Code Playgroud)


小智 15

在角度6和RxJS6中:

import { filter, debounceTime } from 'rxjs/operators';

 this.router.events.pipe(
      filter((event) => event instanceof NavigationEnd),
      debounceTime(40000)
    ).subscribe(
      x => {
      console.log('val',x);
      this.router.navigate(['/']); /*Redirect to Home*/
}
)
Run Code Online (Sandbox Code Playgroud)

  • 你错过了从"@ angular/router"`导入路由器`import {Router,NavigationEnd}的导入 (2认同)

Dan*_*ris 14

在 Angular 10 中,您可以执行以下操作...

    import { Component, OnInit } from '@angular/core';
    import { Router, NavigationEnd } from '@angular/router';
    import { filter } from 'rxjs/operators';
    
    @Component({
      selector: 'app-my-class',
      templateUrl: './my-class.component.html',
      styleUrls: ['./my-class.component.scss']
    })
    export class MyClassComponent implements OnInit {
      constructor(private router: Router) {}
    
      ngOnInit(): void {
        this.router.events
        .pipe(filter(event => event instanceof NavigationEnd))  
        .subscribe((event: NavigationEnd) => {
          // code goes here...
        });
      }
    }
Run Code Online (Sandbox Code Playgroud)


Deh*_*hli 13

这里的答案是正确的router-deprecated.对于最新版本router:

this.router.changes.forEach(() => {
    // Do whatever in here
});
Run Code Online (Sandbox Code Playgroud)

要么

this.router.changes.subscribe(() => {
     // Do whatever in here
});
Run Code Online (Sandbox Code Playgroud)

要查看两者之间的差异,请查看此SO问题.

编辑

最新的你必须做的:

this.router.events.subscribe(event: Event => {
    // Handle route change
});
Run Code Online (Sandbox Code Playgroud)


Dyl*_*sky 12

在花了一些时间搜索解决方案后,我发现了 Angular 13.1.1 的两个更新的解决方法:

  1. 第一个选项:
  constructor(private router: Router) {
    router.events.forEach((event) => {
      if (event instanceof NavigationStart) {
        // Your code
        // Use (event.url) to get URL that is being navigated
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)
  1. 第二个选项

 routerSubscription: Subscription | undefined;

 constructor(private router: Router) {}


  ngAfterViewInit(): void {
    this.routerSubscription = this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
          // Your code
          // Use (event.url) to get URL that is being navigated
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)

记得取消订阅销毁cicle

 ngOnDestroy(): void {
    this.routerSubscription?.unsubscribe();
  }
Run Code Online (Sandbox Code Playgroud)

还要注意根据您的情况使用是否更好

NavigationStart 的事件实例

或者

NavigationEnd 的事件实例


web*_*ean 11

位置有效...

import {Component, OnInit} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit {

    constructor(private location: Location) {
        this.location.onUrlChange(x => this.urlChange(x));
    }

    ngOnInit(): void {}

    urlChange(x) {
        console.log(x);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ash*_*zak 10

如果您在侦听路线更改时尝试访问当前路线:

router.events.pipe(filter(r=>r instanceof NavigationEnd)).subscribe(r=>{
      console.log((r as NavigationEnd).url);
    });
Run Code Online (Sandbox Code Playgroud)


moj*_*ani 7

在组件中,您可能想要尝试以下操作:

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

constructor(private router: Router) {
router.events.subscribe(
        (event) => {
            if (event instanceof NavigationStart)
                // start loading pages
            if (event instanceof NavigationEnd) {
                // end of loading paegs
            }
        });
}
Run Code Online (Sandbox Code Playgroud)


Nar*_*yal 5

以下列方式捕获路线更改事件......

import { Component, OnInit, Output, ViewChild } from "@angular/core";
import { Router, NavigationStart, NavigationEnd, Event as NavigationEvent } from '@angular/router';

@Component({
    selector: "my-app",
    templateUrl: "app/app.component.html",
    styleUrls: ["app/app.component.css"]
})
export class AppComponent {

    constructor(private cacheComponentObj: CacheComponent,
        private router: Router) {

        /*  Route event types
            NavigationEnd
            NavigationCancel
            NavigationError
            RoutesRecognized
        */
        router.events.forEach((event: NavigationEvent) => {

            //Before Navigation
            if (event instanceof NavigationStart) {
                switch (event.url) {
                case "/app/home":
                {
                    //Do Work
                    break;
                }
                case "/app/About":
                {
                    //Do Work
                    break;
                }
                }
            }

            //After Navigation
            if (event instanceof NavigationEnd) {
                switch (event.url) {
                case "/app/home":
                {
                    //Do Work
                    break;
                }
                case "/app/About":
                {
                    //Do Work
                    break;
                }
                }
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)


yal*_*esh 5

以上大多数解决方案都是正确的,但我面临着多次发出“导航发出”事件的问题。当我更改任何路线时,会触发此事件。因此,hear 是 Angular 6 的完整解决方案。

import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';    

export class FooComponent implements OnInit, OnDestroy {
   private _routerSub = Subscription.EMPTY;
   constructor(private router: Router){}

   ngOnInit(){
     this._routerSub = this.router.events
      .filter(event => event instanceof NavigationEnd)
      .subscribe((value) => {
         //do something with the value
     });
  }

  ngOnDestroy(){
   this._routerSub.unsubscribe();
  }
} 
Run Code Online (Sandbox Code Playgroud)