想要在 Angular 2 中路由时防止组件重新创建
Want to prevent Component recreation while routing in Angular 2
假设我们有两条路线 Dashboard
和 Profile
。 Dashboard
具有类似 Google spreadsheet
的动态标签功能。我想做一些交互(构建图表,可视化一些数据)在 Dashboard
中创建选项卡。现在,如果我路由到 Profile
,然后路由回 Dashboard
,我想查看之前在 Dashboard
中的那些选项卡中的内容。这意味着,我想在客户端维护状态。 AFAIK 在组件之间进行路由时,它会重新创建组件。使用 angular 2 路由时是否可以制作类似电子表格的应用程序?我需要使用路由,因为在我的应用程序中我必须使用 LazyLoading 功能。
那么想法应该是什么?我是 angular 2.
的新手
目前组件被重用只有当只有路线参数改变而保持在同一路线上时。
如果路由发生变化,当新路由添加相同的组件时,将重新创建组件。
首选的解决方法是将模型保存在路由更改期间保持活动状态的共享服务中,并使用来自该服务的数据来恢复组件的先前状态。
有人提到有计划支持路由器的自定义重用策略,但没有时间表何时可用。
更新
Angular2 添加了对自定义重用策略的支持。
另见
感谢@Günter Zöchbauer 提供的示例,为了我自己的理解,我决定提炼一个最小的示例。
总结:
首先我实现了一个RouteReuseStrategy:
export class CustomReuseStrategy implements RouteReuseStrategy {
handlers: {[key: string]: DetachedRouteHandle} = {};
calcKey(route: ActivatedRouteSnapshot) {
let next = route;
let url = '';
while(next) {
if (next.url) {
url = next.url.join('/');
}
next = next.firstChild;
}
return url;
}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.handlers[this.calcKey(route)] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!route.routeConfig && !!this.handlers[this.calcKey(route)];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.routeConfig) { return null; }
return this.handlers[this.calcKey(route)];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return this.calcKey(curr) === this.calcKey(future);
}
}
在我的 AppModule
中,我添加了一个新的提供商并配置了一些路由:
export const ROUTES: Routes = [
{
path: 'one',
component: OneComponent
},
{
path: 'two',
component: TwoComponent
},
];
@NgModule({
...
imports: [... RouterModule.forRoot(ROUTES)...]
providers: [...{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }...],
...
})
export class AppModule { }
最后,我定义了一些组件如下:
@Component({
selector: 'my-app',
template: `
<a [routerLink]="['/one']" >Route One</a><br>
<a [routerLink]="['/two']" >Route Two</a><br>
<router-outlet></router-outlet>
`
})
export class AppComponent {}
@Component({
selector: 'app-one',
template: `
Route One currently showing<br>
<input type="text" placeholder="enter some text">
`,
})
export class OneComponent {}
@Component({
selector: 'app-two',
template: `
Route Two currently showing<br>
<input type="text" placeholder="enter some text">
`,
})
export class TwoComponent {}
假设我们有两条路线 Dashboard
和 Profile
。 Dashboard
具有类似 Google spreadsheet
的动态标签功能。我想做一些交互(构建图表,可视化一些数据)在 Dashboard
中创建选项卡。现在,如果我路由到 Profile
,然后路由回 Dashboard
,我想查看之前在 Dashboard
中的那些选项卡中的内容。这意味着,我想在客户端维护状态。 AFAIK 在组件之间进行路由时,它会重新创建组件。使用 angular 2 路由时是否可以制作类似电子表格的应用程序?我需要使用路由,因为在我的应用程序中我必须使用 LazyLoading 功能。
那么想法应该是什么?我是 angular 2.
的新手目前组件被重用只有当只有路线参数改变而保持在同一路线上时。
如果路由发生变化,当新路由添加相同的组件时,将重新创建组件。
首选的解决方法是将模型保存在路由更改期间保持活动状态的共享服务中,并使用来自该服务的数据来恢复组件的先前状态。
有人提到有计划支持路由器的自定义重用策略,但没有时间表何时可用。
更新
Angular2 添加了对自定义重用策略的支持。
另见
感谢@Günter Zöchbauer 提供的示例,为了我自己的理解,我决定提炼一个最小的示例。
总结:
首先我实现了一个RouteReuseStrategy:
export class CustomReuseStrategy implements RouteReuseStrategy {
handlers: {[key: string]: DetachedRouteHandle} = {};
calcKey(route: ActivatedRouteSnapshot) {
let next = route;
let url = '';
while(next) {
if (next.url) {
url = next.url.join('/');
}
next = next.firstChild;
}
return url;
}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.handlers[this.calcKey(route)] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!route.routeConfig && !!this.handlers[this.calcKey(route)];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.routeConfig) { return null; }
return this.handlers[this.calcKey(route)];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return this.calcKey(curr) === this.calcKey(future);
}
}
在我的 AppModule
中,我添加了一个新的提供商并配置了一些路由:
export const ROUTES: Routes = [
{
path: 'one',
component: OneComponent
},
{
path: 'two',
component: TwoComponent
},
];
@NgModule({
...
imports: [... RouterModule.forRoot(ROUTES)...]
providers: [...{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }...],
...
})
export class AppModule { }
最后,我定义了一些组件如下:
@Component({
selector: 'my-app',
template: `
<a [routerLink]="['/one']" >Route One</a><br>
<a [routerLink]="['/two']" >Route Two</a><br>
<router-outlet></router-outlet>
`
})
export class AppComponent {}
@Component({
selector: 'app-one',
template: `
Route One currently showing<br>
<input type="text" placeholder="enter some text">
`,
})
export class OneComponent {}
@Component({
selector: 'app-two',
template: `
Route Two currently showing<br>
<input type="text" placeholder="enter some text">
`,
})
export class TwoComponent {}