Ionic/Angular 嵌套 router-outlet: routerLinks 只工作一次
Ionic/Angular nested router-outlet: routerLinks only work once
我正在尝试使用 Angular's routing guide 在 Angular Ionic v5 应用程序中实现 nested/child 路由的简单示例。我使用 ionic start
创建了一个项目并选择了 blank
模板,然后创建了两个组件 ChildAComponent
和 ChildBComponent
。这是来自 home.page.html
:
的相关代码片段
<div id="container">
<strong>Ready to create an app?</strong>
<p>Start with Ionic <a target="_blank" rel="noopener noreferrer"
href="https://ionicframework.com/docs/components">UI Components</a></p>
<div id="stuff">
<a routerLink="child-a">Child A</a><br>
<a routerLink="child-b">Child B</a><br>
<a routerLink="404">404</a>
</div>
<div id="thing">
<router-outlet></router-outlet>
</div>
</div>
我正在尝试使用 a
标签来驱动 router-outlet
中呈现的组件。当我第一次加载页面 (URL: /home
) 时,我可以单击其中一个 link,相应的 child 元素会在出口中呈现。 发生这种情况时,不过,a
标签上的 href
(我假设它是由 Angular 根据 routerLink
s) 全部改到navigated-to URL.
因此,如果不重新加载页面(返回 /home
),我无法单击另一个组件 link 来呈现该组件。
在单击 link 之前(URL 是 /home
):
点击后Child一个link(URL是/home/childa
):
Angular 文档似乎没有表明我配置有误,而且与 heroes example 中的路由相比,我的代码中没有任何明显不同。我做错了什么?
这是我的 home-routing.module.ts
如果有帮助的话:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomePage } from './home.page';
import { ChildAComponent } from './childa/childa.component';
import { ChildBComponent } from './childb/childb.component';
const routes: Routes = [
{
path: '',
component: HomePage,
children: [
{
path: 'child-a',
component: ChildAComponent,
},
{
path: 'child-b',
component: ChildBComponent,
},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomePageRoutingModule {}
简答
您必须将 绝对路径 添加到 RouterLink
指令中:
<a [routerLink]="['/home', 'child-a']">Child A</a><br>
<a [routerLink]="['/home', 'child-b']">Child B</a><br>
详细解答
让我们先了解一下RouterLink
(特别是RouterLinkWithRef
)指令是如何工作的。它将导航到的路线取决于当前激活的路线(ActivatedRoute
)。这是 what happens 当您单击带有 RouterLinkWithRef
指令的元素时(例如 selector: 'a[routerLink]'
):
/* ... */
this.router.navigateByUrl(this.urlTree, extras);
/* ... */
其中 this.urlTree
定义为 getter
:
get urlTree(): UrlTree {
return this.router.createUrlTree(this.commands, {
relativeTo: this.route, // !
queryParams: this.queryParams,
fragment: this.fragment,
preserveQueryParams: attrBoolValue(this.preserve),
queryParamsHandling: this.queryParamsHandling,
preserveFragment: attrBoolValue(this.preserveFragment),
});
}
我们可以看到,有relativeTo: this.route
,其中this.route
是injected as ActivatedRoute
。
这就是问题出现的原因:当当前路由为/home
时,指令中注入的激活路由应该与来自/home/child-*
的路由不同;在这种情况下,它是相同的。
因此,当用户首次登陆/home
时,指令中注入的ActivatedRoute
将具有一定的值,我们称之为X
。但是当用户转到 /home/child-a
时,router-outlet
之外的视图保持不变,ActivatedRoute
的值也是如此。这很重要,因为在处理绝对和相对路由路径时(提供给路由器指令的任何没有前缀 /
的东西),Angular 将遍历当前的 UrlTree
(UrlTree
= 作为字符串提供的路由路径的反序列化版本)并将尝试用新部分替换旧部分。
用户导航到 /home/child-a
后,然后在当前 UrlTree
中无法在指令中找到从当前 ActivatedRoute
创建的旧部分,因为 ActivatedRoute
不再对应于 actual 激活的路线,所以它是 outdated.
我正在尝试使用 Angular's routing guide 在 Angular Ionic v5 应用程序中实现 nested/child 路由的简单示例。我使用 ionic start
创建了一个项目并选择了 blank
模板,然后创建了两个组件 ChildAComponent
和 ChildBComponent
。这是来自 home.page.html
:
<div id="container">
<strong>Ready to create an app?</strong>
<p>Start with Ionic <a target="_blank" rel="noopener noreferrer"
href="https://ionicframework.com/docs/components">UI Components</a></p>
<div id="stuff">
<a routerLink="child-a">Child A</a><br>
<a routerLink="child-b">Child B</a><br>
<a routerLink="404">404</a>
</div>
<div id="thing">
<router-outlet></router-outlet>
</div>
</div>
我正在尝试使用 a
标签来驱动 router-outlet
中呈现的组件。当我第一次加载页面 (URL: /home
) 时,我可以单击其中一个 link,相应的 child 元素会在出口中呈现。 发生这种情况时,不过,a
标签上的 href
(我假设它是由 Angular 根据 routerLink
s) 全部改到navigated-to URL.
因此,如果不重新加载页面(返回 /home
),我无法单击另一个组件 link 来呈现该组件。
在单击 link 之前(URL 是 /home
):
点击后Child一个link(URL是/home/childa
):
Angular 文档似乎没有表明我配置有误,而且与 heroes example 中的路由相比,我的代码中没有任何明显不同。我做错了什么?
这是我的 home-routing.module.ts
如果有帮助的话:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomePage } from './home.page';
import { ChildAComponent } from './childa/childa.component';
import { ChildBComponent } from './childb/childb.component';
const routes: Routes = [
{
path: '',
component: HomePage,
children: [
{
path: 'child-a',
component: ChildAComponent,
},
{
path: 'child-b',
component: ChildBComponent,
},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomePageRoutingModule {}
简答
您必须将 绝对路径 添加到 RouterLink
指令中:
<a [routerLink]="['/home', 'child-a']">Child A</a><br>
<a [routerLink]="['/home', 'child-b']">Child B</a><br>
详细解答
让我们先了解一下RouterLink
(特别是RouterLinkWithRef
)指令是如何工作的。它将导航到的路线取决于当前激活的路线(ActivatedRoute
)。这是 what happens 当您单击带有 RouterLinkWithRef
指令的元素时(例如 selector: 'a[routerLink]'
):
/* ... */
this.router.navigateByUrl(this.urlTree, extras);
/* ... */
其中 this.urlTree
定义为 getter
:
get urlTree(): UrlTree {
return this.router.createUrlTree(this.commands, {
relativeTo: this.route, // !
queryParams: this.queryParams,
fragment: this.fragment,
preserveQueryParams: attrBoolValue(this.preserve),
queryParamsHandling: this.queryParamsHandling,
preserveFragment: attrBoolValue(this.preserveFragment),
});
}
我们可以看到,有relativeTo: this.route
,其中this.route
是injected as ActivatedRoute
。
这就是问题出现的原因:当当前路由为/home
时,指令中注入的激活路由应该与来自/home/child-*
的路由不同;在这种情况下,它是相同的。
因此,当用户首次登陆/home
时,指令中注入的ActivatedRoute
将具有一定的值,我们称之为X
。但是当用户转到 /home/child-a
时,router-outlet
之外的视图保持不变,ActivatedRoute
的值也是如此。这很重要,因为在处理绝对和相对路由路径时(提供给路由器指令的任何没有前缀 /
的东西),Angular 将遍历当前的 UrlTree
(UrlTree
= 作为字符串提供的路由路径的反序列化版本)并将尝试用新部分替换旧部分。
用户导航到 /home/child-a
后,然后在当前 UrlTree
中无法在指令中找到从当前 ActivatedRoute
创建的旧部分,因为 ActivatedRoute
不再对应于 actual 激活的路线,所以它是 outdated.