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

时间:2015-11-04 10:56:58

标签: angular

我希望在AppComponent中检测路线更改。

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

25 个答案:

答案 0 :(得分:376)

在Angular 2中,您可以this(Rx事件)到Router实例。 所以你可以做像

这样的事情
subscribe

修改(自rc.1起)

class MyClass {
  constructor(private router: Router) {
    router.subscribe((val) => /*whatever*/)
  }
}

编辑2 (自2.0.0开始)

另见:Router.events doc

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

答案 1 :(得分:265)

RxJS 6

router.events.pipe(filter(event => event instanceof NavigationStart))

感谢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
  });
}

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

import 'rxjs/add/operator/filter';

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

使用pairwise operator获取上一个和当前事件也是一个不错的主意。 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);
        });
    };
}

答案 2 :(得分:44)

对于 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);
            }
        });

   }
}

答案 3 :(得分:35)

Angular 4.x及以上:

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

this.activatedRoute.url.subscribe(url =>{
     console.log(url);
});

注意: 您需要从angular/router

导入和注入提供程序
import { ActivatedRoute } from '@angular/router`

constructor(private activatedRoute : ActivatedRoute){  }

答案 4 :(得分:26)

在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
            }
        });
   }
}

答案 5 :(得分:23)

角度7 ,如果您想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);
  });
}

答案 6 :(得分:16)

路由器3.0.0-beta.2应该是

this.router.events.subscribe(path => {
  console.log('path = ', path);
});

答案 7 :(得分: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*/
}
)

答案 8 :(得分:13)

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

this.router.changes.forEach(() => {
    // Do whatever in here
});

this.router.changes.subscribe(() => {
     // Do whatever in here
});

要查看两者之间的差异,请查看this SO question

修改

最新的你必须这样做:

this.router.events.subscribe(event: Event => {
    // Handle route change
});

答案 9 :(得分:7)

在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...
        });
      }
    }

答案 10 :(得分: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;
                }
                }
            }
        });
    }
}

答案 11 :(得分:2)

@Ludohen 答案很棒,但如果您不想使用int deltaGivenByUser = scan.nextInt(); for(int i = 0; i < array.length; i++){ for(int j = 0; j < array.length; j++){ if(Math.abs(array[i][j] - average) >= deltaGivenByUser) { ... ,请使用以下

instanceof

通过这种方式,您可以将当前事件名称检查为字符串,如果事件发生,您可以执行您计划的功能。

答案 12 :(得分:2)

我会这样写:

ngOnInit() {
this.routed = this.router.events.map( event => event instanceof NavigationStart )
  .subscribe(() => {
  } );
}

ngOnDestroy() {
this.routed.unsubscribe();
}

答案 13 :(得分:1)

为使用 Angular9+ 的用户更新了答案,通过使用 @angular/router 提供的路由器 API 并监听路由变化

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

    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      
      name = 'Get Current Url Route Demo';
      currentRoute: string;
     routeSubscription: subscription;
    
      constructor(private router: Router){
        console.log(router.url);
        
        this.routeSubscription = router.events.filter(event => event instanceof NavigationEnd)
              .subscribe(event => 
               {
                  this.currentRoute = event.url;          
                  console.log(event);
               });
        }
    }

答案 14 :(得分:1)

在组件中,您可能想尝试一下:

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
            }
        });
}

答案 15 :(得分:1)

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

MAVEN_OPTS = -Xmx2048M -Xss128M -XX:MaxPermSize=2048M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC

答案 16 :(得分:1)

我正在使用angular5应用程序,并且遇到了相同的问题。当我浏览Angular文档时,它们为处理路由器事件提供了最佳解决方案。请查看以下文档。

  

表示导航成功结束时触发的事件

如何使用此功能?

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRouteSnapshot, NavigationEnd } from '@angular/router';
@Component({
    selector: 'app-navbar',
    templateUrl: './navbar.component.html',
    styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
    constructor(private router: Router) { }
    ngOnInit(): void {
        //calls this method when navigation ends
        this.router.events.subscribe(event => {
            if (event instanceof NavigationEnd) {
                //calls this stuff when navigation ends
                console.log("Event generated");
            }
        });
    }
}

何时使用此功能?

就我而言,我的应用程序为所有用户(例如users,Admins)共享一个通用仪表板,但是我需要根据用户类型显示和隐藏一些导航栏选项。

这就是为什么每当url更改时我都需要调用service方法,该服务方法将根据响应返回登录的用户信息,我将进行进一步的操作。

答案 17 :(得分:0)

只需像在AppRoutingModule上进行更改

@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
  exports: [RouterModule]
})

答案 18 :(得分:0)

角度8。检查当前路线是否为基本路线

  baseroute: boolean;
  constructor(
    private router: Router,
  ) {
    router.events.subscribe((val: any) => {
      if (val.url == "/") {
        this.baseroute = true;
      } else {
        this.baseroute = false;
      }
    });
  }

答案 19 :(得分:0)

位置正常...

add_filter( 'pre_get_posts', 'filterReports' );

function filterReports( $query ) {
  if( is_post_type_archive( 'reports' ) && $_GET['top'] ) {
    // somehow construct a query that checks if sum / count >= 4
  }
}

答案 20 :(得分:0)

我从RC 5开始这样做。

this.router.events
  .map( event => event instanceof NavigationStart )
  .subscribe( () => {
    // TODO
  } );

答案 21 :(得分:0)

更简洁的方法是继承 RouteAware 并实现 onNavigationEnd() 方法。

它是名为 @bespunky/angular-zen 的库的一部分。

  1. <块引用>

    npm install @bespunky/angular-zen

  2. 使您的 AppComponent 扩展 RouteAware 并添加一个 onNavigationEnd() 方法。

import { Component     } from '@angular/core';
import { NavigationEnd } from '@angular/router';
import { RouteAware    } from '@bespunky/angular-zen/router-x';

@Component({
    selector   : 'app-root',
    templateUrl: './app.component.html',
    styleUrls  : ['./app.component.css']
})
export class AppComponent extends RouteAware
{    
    protected onNavigationEnd(event: NavigationEnd): void
    {
        // Handle authentication...
    }
}
<块引用>

RouteAware 还有其他好处,例如:
✨ 任何路由事件都可以有一个处理程序方法(Angular's supported router events)。
✨ 使用 this.router 访问路由器
✨ 使用 this.route 访问激活的路由
✨ 使用 this.componentBus 访问 RouterOutletComponentBus 服务

答案 22 :(得分:0)

我使用这种方式:

class ClassName {
  constructor(private router: Router) {
    router.events.subscribe((value) => {
        // see this 
        console.log(value instanceof NavigationEnd) 
    });
  }
}

答案 23 :(得分:0)

以下几种作品可能对您有用。

// in constructor of your app.ts with router and auth services injected
router.subscribe(path => {
    if (!authService.isAuthorised(path)) //whatever your auth service needs
        router.navigate(['/Login']);
    });

不幸的是,这会在路由过程中稍后重定向,而不是我喜欢的。在重定向之前调用原始目标组件的onActivate()

您可以在目标组件上使用@CanActivate装饰器,但这是a)非集中式,b)不会从注入的服务中受益。

如果有人能够在提交路线之前提出更好的集中授权方式,那将会很棒。我确信必须有更好的方法。

这是我目前的代码(如何更改它以收听路线更改?):

import {Component, View, bootstrap, bind, provide} from 'angular2/angular2';
import {ROUTER_BINDINGS, RouterOutlet, RouteConfig, RouterLink, ROUTER_PROVIDERS, APP_BASE_HREF} from 'angular2/router';    
import {Location, LocationStrategy, HashLocationStrategy} from 'angular2/router';

import { Todo } from './components/todo/todo';
import { About } from './components/about/about';

@Component({
    selector: 'app'
})

@View({
    template: `
        <div class="container">
            <nav>
                <ul>
                    <li><a [router-link]="['/Home']">Todo</a></li>
                    <li><a [router-link]="['/About']">About</a></li>
                </ul>
            </nav>
            <router-outlet></router-outlet>
        </div>
    `,
    directives: [RouterOutlet, RouterLink]
})

@RouteConfig([
    { path: '/', redirectTo: '/home' },
    { path: '/home', component: Todo, as: 'Home' },
    { path: '/about', component: About, as: 'About' }
])

class AppComponent {    
    constructor(location: Location){
        location.go('/');
    }    
}    
bootstrap(AppComponent, [ROUTER_PROVIDERS, provide(APP_BASE_HREF, {useValue: '/'})]);

答案 24 :(得分:-1)

简单的答案 角度8。*

constructor(private route:ActivatedRoute) {
  console.log(route);
}