Angular Router.url与window.location.href不一致 如何正确获取路由URL
问题原因
root级服务的实例化时机早于Angular Router完成首次导航同步的时机。
Router的url属性初始默认值为/,只有在Router完成首次路由解析、触发NavigationEnd事件后,才会将浏览器当前地址同步到该属性。如果服务在Angular应用启动阶段就被实例化(比如被其他启动阶段的服务、组件依赖),此时直接读取this._router.url只能拿到初始值/。这也是问题偶发的核心原因:如果服务首次被调用的时机在首次导航结束之后,就能正常拿到正确的url值。
可行解决方案
不要在服务构造函数中直接读取Router的url属性,以下两种方案均不依赖window对象,可以稳定获取准确的当前地址:
方案1:监听路由导航完成事件,同步完成后再执行初始化逻辑
这是最符合Angular路由设计规范的实现方式:
import { Injectable } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; import { filter, take } from 'rxjs/operators'; @Injectable({ providedIn: 'root', }) export class MyService { constructor(private _router: Router) { this._router.events.pipe( filter(event => event instanceof NavigationEnd), take(1) ).subscribe(() => { this.init() }) } init() { console.log('当前路由url', this._router.url) // 此处编写基于url的API请求逻辑 } }
实现注意点:
filter用来筛选导航完成事件,只有路由同步结束后才会执行后续逻辑take(1)表示只取首次导航完成的结果,执行后自动取消订阅,避免内存泄漏
方案2:注入Angular内置Location服务直接获取当前路径
Angular的Location服务是框架对浏览器地址能力的封装,不直接依赖全局window对象,在应用初始化阶段就能拿到准确的当前路径,不需要等待路由事件:
import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { Location } from '@angular/common'; @Injectable({ providedIn: 'root', }) export class MyService { constructor( private _router: Router, private _location: Location ) { this.init() } init() { const currentPath = this._location.path(); console.log('当前路径', currentPath); // 此处编写基于url的API请求逻辑 } }
该方案自动适配路由模式:如果应用使用
HashLocationStrategy(哈希路由模式),Location.path()会自动返回哈希片段后的路径内容,和Router返回的路径规则完全一致,不需要额外做兼容处理。
内容的提问来源于stack exchange,提问作者Raphaël Balet
相关产品推荐
相关产品推荐

