![](/img/trans.png)
[英]How to Detect route change in angular 6 application using Javascript or Jquery?
[英]How to detect a route change in Angular?
我正在尋找檢測我的AppComponent
中的路由更改。
此后,我將檢查全局用戶令牌以查看用戶是否已登錄,以便在用戶未登錄時重定向用戶。
在 Angular 2 中,您可以subscribe
(Rx 事件)到路由器實例。 所以你可以做類似的事情
class MyClass {
constructor(private router: Router) {
router.subscribe((val) => /*whatever*/)
}
}
編輯(自 rc.1 起)
class MyClass {
constructor(private router: Router) {
router.changes.subscribe((val) => /*whatever*/)
}
}
編輯 2 (從 2.0.0 開始)
另請參閱: Router.events 文檔
class MyClass {
constructor(private router: Router) {
router.events.subscribe((val) => {
// see also
console.log(val instanceof NavigationEnd)
});
}
}
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
運算符來獲取先前和當前事件也是一個好主意。 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); }); }; }
對於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);
}
});
}
}
Angular 7 ,如果你想subscribe
router
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);
});
}
Angular 4.x 及更高版本:
這可以使用ActivatedRoute類的 url 屬性來實現,如下所示,
this.activatedRoute.url.subscribe(url =>{
console.log(url);
});
注意:您需要從angular/router
包中導入和注入提供程序
import { ActivatedRoute } from '@angular/router`
和
constructor(private activatedRoute : ActivatedRoute){ }
在 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
}
});
}
}
在角度 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*/
}
)
路由器 3.0.0-beta.2 應該是
this.router.events.subscribe(path => {
console.log('path = ', path);
});
在 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...
});
}
}
這里的答案對於router-deprecated
是正確的。 對於最新版本的router
:
this.router.changes.forEach(() => {
// Do whatever in here
});
或者
this.router.changes.subscribe(() => {
// Do whatever in here
});
要查看兩者之間的區別,請查看這個 SO question 。
編輯
對於最新的,您必須執行以下操作:
this.router.events.subscribe(event: Event => {
// Handle route change
});
在組件中,您可能想試試這個:
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
}
});
}
位置工作...
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);
}
}
通過以下方式捕獲路線更改事件...
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;
}
}
}
});
}
}
如果您在收聽路由更改時嘗試訪問當前路由:
router.events.pipe(filter(r=>r instanceof NavigationEnd)).subscribe(r=>{
console.log((r as NavigationEnd).url);
});
以上大多數解決方案都是正確的,但我面臨多次發出“導航發出”事件的問題。當我更改任何路線時,會觸發此事件。 所以聽到的是 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();
}
}
為使用 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);
});
}
}
我會寫這樣的東西:
ngOnInit() {
this.routed = this.router.events.map( event => event instanceof NavigationStart )
.subscribe(() => {
} );
}
ngOnDestroy() {
this.routed.unsubscribe();
}
@Ludohen的答案很好,但如果您不想使用instanceof
,請使用以下命令
this.router.events.subscribe(event => {
if(event.constructor.name === "NavigationStart") {
// do something...
}
});
通過這種方式,您可以將當前事件名稱作為字符串檢查,如果事件發生,您可以執行您計划函數執行的操作。
在 Angular 7 中,我已經解決了使用以下函數在特定頁面上啟用和禁用導航欄的問題。
首先你應該導入NavigationEnd
import { NavigationEnd, Router } from '@angular/router';
navbar.component.ts
public isNavbar=false;
ngAfterViewInit() {
// nabar enable / disable function
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
if(event.url.includes('dashboard')){
this.isNavbar=true;
}else{
this.isNavbar=false;
}
}
});
}
navbar.component.html
<mat-toolbar *ngIf="isNavbar" class="mat-elevation-z1 nav-tool-bar">
<button mat-button routerLink="/dashboard" routerLinkActive="active-list-item"><svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="paper-plane" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="nav-bar-icon svg-inline--fa fa-paper-plane fa-w-16"><path fill="currentColor" d="M464 4.3L16 262.7C-7 276-4.7 309.9 19.8 320L160 378v102c0 30.2 37.8 43.3 56.7 20.3l60.7-73.8 126.4 52.2c19.1 7.9 40.7-4.2 43.8-24.7l64-417.1C515.7 10.2 487-9 464 4.3zM192 480v-88.8l54.5 22.5L192 480zm224-30.9l-206.2-85.2 199.5-235.8c4.8-5.6-2.9-13.2-8.5-8.4L145.5 337.3 32 290.5 480 32l-64 417.1z" class=""></path></svg>
Campagnes</button>
<button mat-button routerLink="fake" routerLinkActive="active-list-item"><svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="box-open" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 608 512" class="nav-bar-icon svg-inline--fa fa-box-open fa-w-19"><path fill="currentColor" d="M606.4 143.8L557.5 41c-2.7-5.6-8.1-9-13.9-9C543 32 304 64 304 64S65 32 64.4 32c-5.8 0-11.2 3.5-13.9 9L1.6 143.8c-4.4 9.2.3 20.2 9.6 23l49.5 14.9V393c0 14.7 9.5 27.5 23 31l205.4 54.1c13 3.4 23.7 1.5 29.5 0L524.2 424c13.5-3.6 23-16.4 23-31V181.7l49.5-14.9c9.4-2.8 14-13.8 9.7-23zM73 65.3l180.9 24.3-57.1 99.8-159.9-48.1 36.1-76zm18.2 125.6C208.3 226.1 200.5 224 203.6 224c5.4 0 10.5-2.9 13.3-7.9l71.9-125.5V445L91.2 393V190.9zM516.8 393l-197.6 52V90.5L391.1 216c2.9 5 8 7.9 13.3 7.9 3.1 0-5 2.1 112.4-33.1V393zM411.3 189.3l-57.1-99.8L535 65.3l36.1 76-159.8 48z" class=""></path></svg>
Ressources</button>
<button mat-button routerLink="fake" routerLinkActive="active-list-item"><svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="life-ring" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="nav-bar-icon svg-inline--fa fa-life-ring fa-w-16"><path fill="currentColor" d="M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm168.766 113.176l-62.885 62.885a128.711 128.711 0 0 0-33.941-33.941l62.885-62.885a217.323 217.323 0 0 1 33.941 33.941zM256 352c-52.935 0-96-43.065-96-96s43.065-96 96-96 96 43.065 96 96-43.065 96-96 96zM363.952 68.853l-66.14 66.14c-26.99-9.325-56.618-9.33-83.624 0l-66.139-66.14c66.716-38.524 149.23-38.499 215.903 0zM121.176 87.234l62.885 62.885a128.711 128.711 0 0 0-33.941 33.941l-62.885-62.885a217.323 217.323 0 0 1 33.941-33.941zm-52.323 60.814l66.139 66.14c-9.325 26.99-9.33 56.618 0 83.624l-66.139 66.14c-38.523-66.715-38.5-149.229 0-215.904zm18.381 242.776l62.885-62.885a128.711 128.711 0 0 0 33.941 33.941l-62.885 62.885a217.366 217.366 0 0 1-33.941-33.941zm60.814 52.323l66.139-66.14c26.99 9.325 56.618 9.33 83.624 0l66.14 66.14c-66.716 38.524-149.23 38.499-215.903 0zm242.776-18.381l-62.885-62.885a128.711 128.711 0 0 0 33.941-33.941l62.885 62.885a217.323 217.323 0 0 1-33.941 33.941zm52.323-60.814l-66.14-66.14c9.325-26.99 9.33-56.618 0-83.624l66.14-66.14c38.523 66.715 38.5 149.229 0 215.904z" class=""></path></svg>Support</button></mat-toolbar>
navbar.component.scss
.mat-toolbar {
padding-top: 2px;
padding-left: 30px;
background-color: #fff;
}
::ng-deep .nav-tool-bar{
button{
.mat-button-focus-overlay{
opacity: 0!important;
}
.nav-bar-icon{
width: 16px;
}
span{
font-size: 15px;
}
}
.active-list-item{
background-color: #c79652;
span{
color: #fff;
font-size: 15px;
svg{
path{
color: #fff;
}
}
}
}
}
對更改 SCSS .active-list-item背景顏色很重要。
我正在使用 angular5 應用程序,我面臨同樣的問題。 當我瀏覽 Angular 文檔時,它們提供了處理路由器事件的最佳解決方案。請查看以下文檔。
Angular 中的路由事件 Angular5中的路由事件
但特別是對於有問題的情況,我們需要NavigationEnd 事件
表示導航成功結束時觸發的事件
這個怎么用?
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 更改時,我需要調用服務方法,該方法根據響應返回登錄的用戶信息,我將進行進一步的操作。
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
this.showProgressBar = true
} else if (event instanceof NavigationEnd) {
this.showProgressBar = false
}
else if (event instanceof NavigationCancel) {
this.showProgressBar = false
}
})
以下類型的作品可能會為您帶來棘手的問題。
// 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: '/'})]);
從 RC 5 開始我就這樣做了
this.router.events
.map( event => event instanceof NavigationStart )
.subscribe( () => {
// TODO
} );
更簡潔的方法是繼承RouteAware
並實現onNavigationEnd()
方法。
它是名為@bespunky/angular-zen的庫的一部分。
npm install @bespunky/angular-zen
讓您的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 支持的路由器事件)。
✨ 使用this.router
訪問路由器
✨ 使用this.route
訪問激活的路由
✨ 使用this.componentBus
訪問 RouterOutletComponentBus 服務
我用這種方式:
class ClassName {
constructor(private router: Router) {
router.events.subscribe((value) => {
// see this
console.log(value instanceof NavigationEnd)
});
}
}
如果您只想檢查路由/查詢參數更改,例如localhost:4200/users/1?edit=1到localhost:4200/users/2?edit=0 ,您可以使用如下所示的 params observable。
import { ActivatedRoute, Params } from '@angular/router';
export class SomeClass implements OnInit {
paramFromRoute;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.paramFromRoute = this.route.snapshot.params['paramName']; // this one is required for getting it first time
this.route.params.subscribe((params:Params)=>{
this.paramFromRoute = params['paramName'] // whenever route is changed, this function will triggered.
});
// for queryParams you can subscribe to this.route.queryParams
}
}
您可以使用以下方法來檢測路由更改:
import { Router, ActivatedRoute} from '@angular/router'; constructor(private route: ActivatedRoute) {} this.router.events.subscribe((event) => { if(event) { //do something } });
在花了一些時間搜索解決方案后,我發現了 Angular 13.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
}
});
}
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 } }); }
記得取消訂閱銷毀循環
ngOnDestroy(): void {
this.routerSubscription?.unsubscribe();
}
還要注意根據您的情況是否更好使用
NavigationStart 的事件實例
或者
NavigationEnd 的事件實例
只需在 AppRoutingModule 上進行更改,例如
@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
exports: [RouterModule]
})
Angular 8. 檢查當前路由是否為基礎路由。
baseroute: boolean;
constructor(
private router: Router,
) {
router.events.subscribe((val: any) => {
if (val.url == "/") {
this.baseroute = true;
} else {
this.baseroute = false;
}
});
}
Angular 8.* 的簡單答案
constructor(private route:ActivatedRoute) {
console.log(route);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.