停止在路线更改时重新加载全部内容
Stop reloading the whole content on route change
我有一个如下所示的路由:page/:id
,它为每个 id
加载不同的内容。但是,每次我转到不同的页面时,它都会重新加载全部内容。我只想重新加载来自 API.
的数据
导航:
<ul>
<li [routerLink]="['/page', 1]">Page 1</li>
<li [routerLink]="['/page', 2]">Page 2</li>
<li [routerLink]="['/page', 3]">Page 3</li>
</ul>
模板:
<h1 *ngIf="data">{{data.name}}</h1>
组件:
export class DataComponent implements OnInit {
data: any;
error: any;
constructor(
private route: ActivatedRoute,
private service: DataService
) {}
ngOnInit() {
this.getData();
}
getData() {
this.service.getData()
.subscribe(
res => this.data = res,
error => this.error = error
);
}
}
如果您转到此 Plunker,您会看到每次路线更改时黑色矩形都会闪烁。理想情况下,黑色部分保持不变,只有里面的数据会发生变化。
我还注意到只有在使用 HTTP 调用时才会出现这种闪烁行为。如果我在那个组件中有其他东西,改变路线时就不会发生这种情况。
关于如何解决这个问题有什么想法吗?
编辑:Here's a Plunkr 显示了预期的行为。但是,我使用的是以前的 ROUTER_DIRECTIVES
,现在已弃用。
您已经只重新加载来自 API 的内容。黑框在闪烁,因为您正在设置 h1
的样式并且 h1
正在更改。如果您希望每个页面都有该框,请将其向上移动到 AppComponent
s 模板。
<div class="box">
<router-outlet></router-outlet>
</div>
然后将样式移动到 .box
选择器而不是 h1
。
另一个问题是当内容被移除和刷新时框的高度会折叠和展开。您可以通过在路线上使用 resolve guard 来解决此问题。
https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard
你的闪烁是因为当你导航时,DataComponent
被破坏并重建,但是直到新数据从服务器到达它才能显示,因为你用 *ngIf="data"
阻止了它的显示。 On this plunker,我在服务器响应中添加了 1 秒的延迟以使问题更加明显。请注意,只有 DataComponent
闪烁。其余 PagesComponent
没有。
On this plunker,没有可见的闪烁,因为数据是硬编码的,所以不需要等待服务器的响应。
为了减轻闪烁,不要使用 *ngIf
,因为那样会从 dom 中完全删除该元素。 On this plunker,甚至在我们等待数据从服务器到达时也没有闪烁。
基本上,只要您选择隐藏元素直到数据到达,无论何时重新初始化组件,您都会看到闪烁。
扩展@Rob 的回答,我确实设法使用 Resolve
守卫解决了这个问题。但是,我在实现过程中犯了一些错误。
我创建了一个新的 data-resolve
,我在初始化路由之前解析了 HTTP
调用:
@Injectable()
export class DataResolve implements Resolve {
constructor(private service: DataService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot):
Observable<any> | Promise<any> | any {
return this.service.getData().then(data => {
if (data) {
return data;
} else {
this.router.navigate(['/page/1']);
return false;
}
});
}
}
然后,我需要将该服务添加到我的模块的提供者中:
providers: [DataService, DataResolve]
并且在加载路由之前告诉路由解决这个问题:
resolve: { pages: DataResolve }
之后,我将有一个数组,我可以在我的组件中使用它来获取数据:
this.route.data.forEach((data: {pages}) => {
this.data = data.pages;
});
我还用一个工作示例更新了我的 Plunker。
我有一个如下所示的路由:page/:id
,它为每个 id
加载不同的内容。但是,每次我转到不同的页面时,它都会重新加载全部内容。我只想重新加载来自 API.
导航:
<ul>
<li [routerLink]="['/page', 1]">Page 1</li>
<li [routerLink]="['/page', 2]">Page 2</li>
<li [routerLink]="['/page', 3]">Page 3</li>
</ul>
模板:
<h1 *ngIf="data">{{data.name}}</h1>
组件:
export class DataComponent implements OnInit {
data: any;
error: any;
constructor(
private route: ActivatedRoute,
private service: DataService
) {}
ngOnInit() {
this.getData();
}
getData() {
this.service.getData()
.subscribe(
res => this.data = res,
error => this.error = error
);
}
}
如果您转到此 Plunker,您会看到每次路线更改时黑色矩形都会闪烁。理想情况下,黑色部分保持不变,只有里面的数据会发生变化。
我还注意到只有在使用 HTTP 调用时才会出现这种闪烁行为。如果我在那个组件中有其他东西,改变路线时就不会发生这种情况。
关于如何解决这个问题有什么想法吗?
编辑:Here's a Plunkr 显示了预期的行为。但是,我使用的是以前的 ROUTER_DIRECTIVES
,现在已弃用。
您已经只重新加载来自 API 的内容。黑框在闪烁,因为您正在设置 h1
的样式并且 h1
正在更改。如果您希望每个页面都有该框,请将其向上移动到 AppComponent
s 模板。
<div class="box">
<router-outlet></router-outlet>
</div>
然后将样式移动到 .box
选择器而不是 h1
。
另一个问题是当内容被移除和刷新时框的高度会折叠和展开。您可以通过在路线上使用 resolve guard 来解决此问题。
https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard
你的闪烁是因为当你导航时,DataComponent
被破坏并重建,但是直到新数据从服务器到达它才能显示,因为你用 *ngIf="data"
阻止了它的显示。 On this plunker,我在服务器响应中添加了 1 秒的延迟以使问题更加明显。请注意,只有 DataComponent
闪烁。其余 PagesComponent
没有。
On this plunker,没有可见的闪烁,因为数据是硬编码的,所以不需要等待服务器的响应。
为了减轻闪烁,不要使用 *ngIf
,因为那样会从 dom 中完全删除该元素。 On this plunker,甚至在我们等待数据从服务器到达时也没有闪烁。
基本上,只要您选择隐藏元素直到数据到达,无论何时重新初始化组件,您都会看到闪烁。
扩展@Rob 的回答,我确实设法使用 Resolve
守卫解决了这个问题。但是,我在实现过程中犯了一些错误。
我创建了一个新的 data-resolve
,我在初始化路由之前解析了 HTTP
调用:
@Injectable()
export class DataResolve implements Resolve {
constructor(private service: DataService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot):
Observable<any> | Promise<any> | any {
return this.service.getData().then(data => {
if (data) {
return data;
} else {
this.router.navigate(['/page/1']);
return false;
}
});
}
}
然后,我需要将该服务添加到我的模块的提供者中:
providers: [DataService, DataResolve]
并且在加载路由之前告诉路由解决这个问题:
resolve: { pages: DataResolve }
之后,我将有一个数组,我可以在我的组件中使用它来获取数据:
this.route.data.forEach((data: {pages}) => {
this.data = data.pages;
});
我还用一个工作示例更新了我的 Plunker。