使用 Angular 路由器如何在多个命名插座之间共享路由
Using the Angular router how do I share routes across multiple named outlets
我有一个应用程序,我想在应用程序的多个位置显示同一组组件/路由。想想像多个面板或侧边栏这样的东西,用户可以在多个位置显示相同的组件,具体取决于它们 select。
例如,用户可能想要 "show the status component in side panel" 或 "show the status component in bottom right panel on page"。
(在我的例子中,插座的数量是固定的,但相同的概念可以用于仪表板样式 UI 具有动态数量的卡片,每个卡片都有一个组件加载路径)
我的想法是为此使用带有命名插座的 angular 路由器。这将允许轻松重用支持动态创建的组件,并将当前路由状态保持在 URL 中以便于重新加载。
因此,例如 url 可能如下所示:
https://.../app(side:status_comp//popup:other_comp)
我已经命名了 outlets 工作,但我不知道该怎么做是在不复制路由器配置中的路由的情况下跨多个命名 outlets 重用路由。
例如:
const appRoutes: Routes = [
{ path: 'main', component: AppComponent },
// ==> Have to repeat each route for each outlet name
{ path: 'comp_a', component: CompA, outlet: 'first' },
{ path: 'comp_b', component: CompB, outlet: 'first' },
{ path: 'comp_a', component: CompA, outlet: 'second' },
{ path: 'comp_b', component: CompB, outlet: 'second' },
// ==> Would like to just do this
/*
{ path: 'comp_a', component: CompA},
{ path: 'comp_b', component: CompB},
*/
{ path: '', redirectTo: '/main', pathMatch: 'full' },
{ path: '**', redirectTo: '/main' }
];
简化模板:
<p>Outlet 1</p>
<a [routerLink]="[{ outlets: { first: ['comp_a'] } }]">Comp A</a>
<a [routerLink]="[{ outlets: { first: ['comp_b'] } }]">Comp B</a>
<div class="outlet-wrapper">
<router-outlet name="first"></router-outlet>
</div>
<p>Outlet 2</p>
<a [routerLink]="[{ outlets: { second: ['comp_a'] } }]">Comp A</a>
<a [routerLink]="[{ outlets: { second: ['comp_b'] } }]">Comp B</a>
<div class="outlet-wrapper">
<router-outlet name="second"></router-outlet>
</div>
然后使用以下方法将组件布线到插座中:
this.router.navigate([{outlets: {first: ['comp_a']}}]);
我想要的是仅使用到给定组件的单个路由设置路由器,然后能够使用任何定义的路由调用 router.navigate
,但告诉它在指定的出口中加载该路由。
有什么办法吗
这是 stackblitz 上的示例,我在其中设置了所有内容。 ng-router-reuse app
我要进行的更改显示在上面和路由定义中的相同位置。
有什么想法吗?
注意:我知道我可以使用 Angular CDK 中的 Portals 之类的东西并动态加载组件。但问题是用户所看到的状态不会存储到 URL 中以供路由器管理,而且它还会阻止使用路由器延迟加载。
看起来您可以在运行时在导航时动态更新路由器配置。这是一个例子。 https://stackblitz.com/edit/ng-router-reuse-c7j96a
下面是一个简短的解释。
1) 在 link 或按钮上单击在路由器配置中查找路由。
let route = this.router.config.filter(r => r.path === 'comp_a' && r.outlet === 'second')[0];
2) 如果路由不存在,将其添加到配置中。
if(!route){
this.router.config.unshift({path:'comp_a',outlet:'second',component:CompA})
}
我们在这里使用的是 unshift 方法而不是 push 方法,因为我们不想在最后添加新路由。我们总是希望将 **
作为最后一条路线。
3) 然后简单地导航到路线。
this.router.navigate([{outlets: {second: ['comp_a']}}]);
当应用程序已加载时,此解决方案会很有帮助。但是,如果您尝试加载一个 URL,它有一个带有命名出口的路径,并且如果该路由未在路由器配置中定义,它将抛出一个错误。
要克服这种情况,您可以在模块级别收听 NavigationStart 事件,然后您可以检查 URL 并相应地添加路由。尽管可以做到,但我感觉并不干净。我希望这会有所帮助。
我有一个应用程序,我想在应用程序的多个位置显示同一组组件/路由。想想像多个面板或侧边栏这样的东西,用户可以在多个位置显示相同的组件,具体取决于它们 select。
例如,用户可能想要 "show the status component in side panel" 或 "show the status component in bottom right panel on page"。
(在我的例子中,插座的数量是固定的,但相同的概念可以用于仪表板样式 UI 具有动态数量的卡片,每个卡片都有一个组件加载路径)
我的想法是为此使用带有命名插座的 angular 路由器。这将允许轻松重用支持动态创建的组件,并将当前路由状态保持在 URL 中以便于重新加载。
因此,例如 url 可能如下所示:
https://.../app(side:status_comp//popup:other_comp)
我已经命名了 outlets 工作,但我不知道该怎么做是在不复制路由器配置中的路由的情况下跨多个命名 outlets 重用路由。
例如:
const appRoutes: Routes = [
{ path: 'main', component: AppComponent },
// ==> Have to repeat each route for each outlet name
{ path: 'comp_a', component: CompA, outlet: 'first' },
{ path: 'comp_b', component: CompB, outlet: 'first' },
{ path: 'comp_a', component: CompA, outlet: 'second' },
{ path: 'comp_b', component: CompB, outlet: 'second' },
// ==> Would like to just do this
/*
{ path: 'comp_a', component: CompA},
{ path: 'comp_b', component: CompB},
*/
{ path: '', redirectTo: '/main', pathMatch: 'full' },
{ path: '**', redirectTo: '/main' }
];
简化模板:
<p>Outlet 1</p>
<a [routerLink]="[{ outlets: { first: ['comp_a'] } }]">Comp A</a>
<a [routerLink]="[{ outlets: { first: ['comp_b'] } }]">Comp B</a>
<div class="outlet-wrapper">
<router-outlet name="first"></router-outlet>
</div>
<p>Outlet 2</p>
<a [routerLink]="[{ outlets: { second: ['comp_a'] } }]">Comp A</a>
<a [routerLink]="[{ outlets: { second: ['comp_b'] } }]">Comp B</a>
<div class="outlet-wrapper">
<router-outlet name="second"></router-outlet>
</div>
然后使用以下方法将组件布线到插座中:
this.router.navigate([{outlets: {first: ['comp_a']}}]);
我想要的是仅使用到给定组件的单个路由设置路由器,然后能够使用任何定义的路由调用 router.navigate
,但告诉它在指定的出口中加载该路由。
有什么办法吗
这是 stackblitz 上的示例,我在其中设置了所有内容。 ng-router-reuse app
我要进行的更改显示在上面和路由定义中的相同位置。
有什么想法吗?
注意:我知道我可以使用 Angular CDK 中的 Portals 之类的东西并动态加载组件。但问题是用户所看到的状态不会存储到 URL 中以供路由器管理,而且它还会阻止使用路由器延迟加载。
看起来您可以在运行时在导航时动态更新路由器配置。这是一个例子。 https://stackblitz.com/edit/ng-router-reuse-c7j96a
下面是一个简短的解释。
1) 在 link 或按钮上单击在路由器配置中查找路由。
let route = this.router.config.filter(r => r.path === 'comp_a' && r.outlet === 'second')[0];
2) 如果路由不存在,将其添加到配置中。
if(!route){
this.router.config.unshift({path:'comp_a',outlet:'second',component:CompA})
}
我们在这里使用的是 unshift 方法而不是 push 方法,因为我们不想在最后添加新路由。我们总是希望将 **
作为最后一条路线。
3) 然后简单地导航到路线。
this.router.navigate([{outlets: {second: ['comp_a']}}]);
当应用程序已加载时,此解决方案会很有帮助。但是,如果您尝试加载一个 URL,它有一个带有命名出口的路径,并且如果该路由未在路由器配置中定义,它将抛出一个错误。
要克服这种情况,您可以在模块级别收听 NavigationStart 事件,然后您可以检查 URL 并相应地添加路由。尽管可以做到,但我感觉并不干净。我希望这会有所帮助。