Angular 8开启useHash: true时如何匹配无#前缀的路由地址
问题原因
当Angular路由配置useHash: true时,框架默认采用HashLocationStrategy处理路由,仅会解析URL中#之后的片段作为路由路径,#之前的内容会被当作应用入口的静态资源路径,因此你添加的常规路由规则无法匹配到#之前的无哈希路径。
可行解决方案(不修改useHash配置)
方案1:启动阶段拦截+服务端适配(成本最低)
- 首先配置服务端规则:将你需要匹配的无哈希路径(如
/pageWithoutHash)的请求,指向你的Angular应用入口的index.html,确保用户直接访问该路径时能正常加载Angular应用,不会返回404。 - 在应用初始化阶段拦截路径做对应处理,在根模块添加如下逻辑:
import { APP_INITIALIZER, NgModule } from '@angular/core'; import { Router } from '@angular/router'; import { HashLocationStrategy, LocationStrategy } from '@angular/common'; // 应用初始化拦截器 export function handleNoHashPath(router: Router) { return () => { const fullPath = window.location.pathname; // 匹配你需要处理的特定无哈希路径 if (fullPath === '/pageWithoutHash' || fullPath.endsWith('/pageWithoutHash')) { // 可选1:自动跳转至带哈希的对应路由,地址栏会自动更新为带#格式 router.navigate(['/pageWithoutHash']); // 可选2:保留地址栏无#格式,在根组件中控制对应组件渲染,无需走Angular路由匹配 // 你可以在根组件定义一个变量如showNewComponent = false,这里匹配到路径后设为true // 根模板中加 <app-new-component *ngIf="showNewComponent"></app-new-component> // 同时用replaceState保留原路径不跳转:window.history.replaceState({}, document.title, fullPath); } }; } @NgModule({ providers: [ { provide: LocationStrategy, useClass: HashLocationStrategy }, { provide: APP_INITIALIZER, useFactory: handleNoHashPath, deps: [Router], multi: true } ] }) export class AppModule { }
方案2:自定义路由策略(适配多路径需求)
如果你需要匹配多个无哈希路径,不想单独写判断逻辑,可以自定义LocationStrategy扩展路由匹配规则:
import { HashLocationStrategy } from '@angular/common'; export class CustomHashLocationStrategy extends HashLocationStrategy { override path(includeHash?: boolean): string { const path = super.path(includeHash); // 无哈希路径时直接返回真实pathname给路由匹配 if (!window.location.hash) { return window.location.pathname; } return path; } }
之后在根模块的providers里替换原来的LocationStrategy配置即可:
{ provide: LocationStrategy, useClass: CustomHashLocationStrategy }
此时你原本写的路由规则{ path: 'pageWithoutHash', component: NewComponent, pathMatch: 'prefix' }就可以正常匹配无哈希路径了,原有带哈希的路由也不受影响。
内容的提问来源于stack exchange,提问作者Alps
相关产品推荐
相关产品推荐

