调用router.navigate后如何确定新路由?路由守卫拦截场景
嘿,这个问题我之前帮不少开发者解决过——Angular的CanDeactivate守卫里确实没有直接的this.router.newRoute属性,但完全不用靠全局变量这种不太优雅的方式,有几个更合适的方案:
解决方案:在CanDeactivate守卫中获取目标路由
- 方法1:通过
Router.getCurrentNavigation()获取目标路由
这是最直接的原生方式,当你调用this.router.navigate()时,Angular会生成一个当前导航对象,你可以在守卫里通过它拿到最终的目标路由信息:
import { CanDeactivate } from '@angular/router'; import { Router } from '@angular/router'; import { Injectable } from '@angular/core'; @Injectable() export class MyDeactivateGuard implements CanDeactivate<MyComponent> { constructor(private router: Router) {} canDeactivate(component: MyComponent): boolean | Observable<boolean> { // 获取目标路由的完整URL字符串 const targetUrl = this.router.getCurrentNavigation()?.finalUrl?.toString(); if (targetUrl === '/myApp/userProfiles') { // 这里写你的拦截逻辑,比如确认弹窗 return confirm(`确定要跳转到用户列表页吗?`); } return true; } }
⚠️ 注意:getCurrentNavigation()仅在导航过程中有效,导航完成后会被重置为null,所以一定要在canDeactivate方法内调用它。
- 方法2:通过导航状态传递目标标识
如果你需要更灵活地传递目标路由的自定义信息,可以在调用navigate时附加状态参数,再在守卫里读取:
首先,发起导航时:
this.router.navigate(["myApp/userProfiles"], { state: { targetPage: 'userProfiles' } });
然后在守卫中获取状态:
canDeactivate(component: MyComponent): boolean | Observable<boolean> { const navigationState = this.router.getCurrentNavigation()?.extras.state; if (navigationState?.targetPage === 'userProfiles') { // 执行你的拦截逻辑 return true; } return false; }
- 方法3:监听
Router的NavigationStart事件
你也可以在守卫里订阅路由的NavigationStart事件,实时捕获每次导航的目标URL。但要记得在守卫销毁时取消订阅,避免内存泄漏:
import { Subscription } from 'rxjs'; import { NavigationStart } from '@angular/router'; import { OnDestroy } from '@angular/core'; @Injectable() export class MyDeactivateGuard implements CanDeactivate<MyComponent>, OnDestroy { private navigationSub: Subscription; private targetUrl: string | null = null; constructor(private router: Router) { this.navigationSub = this.router.events.subscribe(event => { if (event instanceof NavigationStart) { this.targetUrl = event.url; } }); } canDeactivate(component: MyComponent): boolean | Observable<boolean> { if (this.targetUrl === '/myApp/userProfiles') { return confirm(`确认离开当前页面跳转到${this.targetUrl}吗?`); } return true; } ngOnDestroy() { this.navigationSub.unsubscribe(); } }
总结一下,优先用第一种方法,它是Angular官方提供的最简洁可靠的方式,不需要额外传递状态或订阅事件。
内容的提问来源于stack exchange,提问作者John Glabb
相关产品推荐
相关产品推荐

