我正在构建一个角度为6的app,应该有两个特定的路由器插座:
<router-outlet name="navbar"></router-outlet>
<router-outlet></router-outlet>
应用程序由URL中指定的令牌驱动:
http://my.app/*token*/dashboard
所以我有这个特定的路由:
const routes: Routes = [
{
path: ':token', component: CoreComponent, children: [
{ path: 'dashboard', component: DashboardComponent },
{ path: 'app1', component: App1Component },
{ path: 'app2', component: App2Component },
{ path: '', component: NavbarComponent, outlet: 'navbar' }
]
}
];
@NgModule({
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
exports: [RouterModule],
declarations: []
})
在每个组件中,我从URL检索token参数并对其执行一些检查 .
constructor(public route: ActivatedRoute,
public router: Router) {
}
ngOnInit() {
this.route.params.subscribe(params => {
let _token: string = params['token'];
// do something
});
}
它在NavbarComponent中完美运行,但我无法在其他组件中获取参数 . 就像参数在导航栏中处理后丢失一样 .
我还没有找到关于这种现象的任何可靠文件 .
这是stackblitz的一个例子
https://stackblitz.com/edit/angular-skvpsp?file=src%2Fapp%2Fdashboard.component.ts
并输入此测试网址:https://angular-skvpsp.stackblitz.io/2345abcf/inbox有关详细信息,请参阅控制台 .
任何的想法?谢谢 .
[EDIT]
试过很多解决方案,但仍未找到正确的答案 .
我看到有一个数据属性可以在路由模块中使用 . 我会检查一下 .
1 回答
初步马克
所以,经过一些调试我发现了问题 .
很抱歉,在解决问题后,我只是为您的代码添加了一些tipp .
TL; DR
我为你准备了一个优化的Stackblitz,检查一下,看看所有的变化!
https://stackblitz.com/edit/angular-l1hhj1
原始问题
看看你的路线:
这些路线和评论存在问题
Angular消耗路径参数 . 所以
:token
param只给AppComponent .以下可能解决方案
无关,但也有代码气味:路由器内的AppComponent
路由器使用基于url的组件填充
<router-outlet>
标记 . 由于AppComponent已经是根组件,因此您将AppComponent加载到其自身的RouterOutlet中 .您的导航栏仅适用,因为您让它与所有网址匹配 .
由于你将它作为子路径放在
:token
路径下面,它也会得到:token
参数,因为你读取它的逻辑位于BasePage.ts`中,它也可以读取它 .So your nav bar only works by accident.
最简单的解决方案
您最简单的解决方案是进入
BasePage.ts
并更改以下代码至
以下是ActivatedRoute类的文档:
https://angular.io/guide/router#activated-route
更多建议
将Stackblitz的应用程序链接集成为默认路由
而不是发布Stackblitz和在stackblitz内部调用的链接,而是将stackblitz中的链接添加为默认路由 . 只需将此路线添加到您的路线阵列,您的Stackblitz将自动加载您想要的路线:
{ path: '', pathMatch: 'full', redirectTo: '2345abcf/inbox' }
不推荐使用
ActivatedRoute.params和ActivatedRoute.queryParam
请改用ActivatedRoute.paramMap和ActivatedRoute.queryParamMap .
见官方角度文档:https://angular.io/guide/router#activated-route
尽可能使用paramMaps的Observable版本
您应该每次使用paramMaps作为Observable而不是snapshot.paramMaps .
快照的问题如下:
路由器激活Component1
例如,在ngOnInit中,ParamSnapshot为红色
路由器激活Component2
路由器再次激活Component1,但使用另一个路径参数 .
2个问题:
ParamSnapshot是不可变的,因此无法访问新值
ngOnInit不再运行,因为组件已经在dom中 .
使用routerLink属性构建路由
请参阅:https://angular.io/guide/router#router-links这可以避免在手动构建路径时出现可能的错误 . 通常,具有两个路由器出口的路由如下所示:
https://some-url.com/home(conference:status/online)
/home
是主要路线,(conference:status/online)
表示<router-outlet name=‚conference‘>
应该加载路线/状态/在线 .由于您省略了第二个插座的最后一个部分,因此不能立即清楚,角度将如何处理路线 .
请勿使用第二个路由器插座进行导航
这使事情变得比他们需要的更复杂 . 您无需单独浏览导航内容,也不需要?如果您不需要单独导航,则可以更轻松地将菜单直接包含在AppComponent模板中 .
当你有一个侧边栏进行聊天时,第二个路由器插座是有意义的,你可以选择联系人,聊天窗口和聊天设置页面,而所有这些都独立于你的主要方面 . 那你需要两个路由器插座 .
使用基类或角度服务
您通过以下方式将您的BasePage作为服务提供给Angular
使用可注入服务作为基类似乎是一个非常奇怪的设计 . 我想不出一个原因,我想用它 . 要么我使用BaseClass作为BaseClass,它独立于角度工作 . 或者我使用角度服务并将其注入到需要服务功能的组件中 .
Note: 您不能简单地创建一个服务,它会注入
Router
和ActivatedRoute
,因为它会获取这些组件的根对象,这些组件是空的 . Angular为每个组件生成自己的ActivatedRoute
实例,并将其注入组件 .解决方案:请参阅'更好解决方案:TokenComponent with Token Service'如下 .
更好的解决方案:使用令牌服务的TokenComponent
我现在能想到的最好的解决方案是与TokenService一起构建TokenComponent . 您可以在Stackblitz查看此创意的工作副本:
https://stackblitz.com/edit/angular-l1hhj1
现在代码的重要部分,万一,Stackblitz将被删除 .
我的TokenService看起来像这样:
此TokenService用于ngOnInit中的TokenComponent:
最后,路由配置将所有这些粘合在一起:
如何立即访问令牌
在您需要令牌的地方注入TokenService .
当您在模板中需要它时,使用异步管道访问它,如下所示:
我希望这会对你有所帮助 . 这是一个有趣的挑战! :)