我有一个条目列表,当我单击一个列表时,会进入该项目的更详细视图。现在,此视图通过http-Request加载(这比从页面到页面的路由花费的时间更长)。假设我有以下代码:
对于目标页面:
projectNumber: string = '';
ngOnInit() {
}
constructor(
private router: Router,
private route: ActivatedRoute,
private logger: LoggerService,
private projectReceiverService: ProjectReceiverService
) {
this.initProjectDataFromProjectNumber(this.route.snapshot.paramMap.get('projectNum'));
}
initProjectDataFromProjectNumber(projectNumber: string) {
let project = this.projectReceiverService.getProjectByNumber(projectNumber);
this.projectNumber = projectNumber; //getProjectNumber => results in error
}
对于服务:
getProjectByNumber(projectNumber: string): Project {
let project: Project;
this.http.get(httpBaseUrl + "/project/getProject/" + projectNumber, httpOptions).subscribe((data) => {
this.logger.info("Received data, processing...");
project = data['projectDto'];
},
(error) => {
this.logger.error("Error when receiving project.");
this.logger.error(error.message);
});;
return project;
}
对于上一页(我在其中单击项目):
projectClicked(projectNumber: string) {
this.routeTo('projects/' + projectNumber);
}
现在,如果我能以某种方式设法在http请求完全成功之后进行路由会很棒(因为我可以例如在路由时直接传递项目对象,而且我也不会因为显示一些数据而费劲可能尚未在详细页面上加载)。我该怎么办?我曾考虑过要在单击某些内容之前先将其加载到前面,但是要过载才能先前加载每个项目的所有详细信息。
答案 0 :(得分:1)
您可以使用路由解析器相对轻松地做到这一点。
它是这样的。在您的路由配置中,提供您的路由路径,组件和一个resolver
。
const routes = [{
path: 'projects/:projectNumber',
component: DestinationComponent,
resolve: {
project: ProjectResolver
},
}];
现在,您必须将此路由放入模块中,并提供您提到的解析器。例如。像这样:
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: [ProjectResolver],
})
export class ProjectDetailsModule {}
但这是什么ProjectResolver?它只是实现Angular的Resolve接口的可注入类,它的resolve()
方法以数据,Promise或Observable的形式返回数据。看起来像这样:
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
// You will also need your service
import { ProjectService } from './project.service';
@Injectable()
export class ProjectResolver implements Resolve {
// Inject it with where the data comes from
constructor(private projectService: ProjectService) {}
// Now implement the resolve interface. Angular will give you the route,
// from which you can read the parameter.
resolve(route: ActivatedRouteSnapshot): Observable<Project> {
const projectNumber = route.snapshot.params['projectNumber'];
return this.projectService.getProjectByNumber(projectNumber);
}
}
现在,我们必须修复一些服务-http方法通常是异步的,因此您必须返回可观察的值:
// I'll change the return type, from Project, to Obsevable<Project>
getProjectByNumber(projectNumber: string): Observable<Project> {
return this.http.get(`${ httpBaseUrl }/project/getProject/${ projectNumber }`, httpOptions)
// Instead of subscribe, you'll use a pipe, to map. So that others can actually subscribe (in our case the Angular router)
.pipe(
map(data => {
this.logger.info("Received data, processing...");
project = data['projectDto'];
return project;
// This whole `map(...)` part could have been a one-liner:
// map(data => data.projectDto)
// so alltogether:
// this.http.get().pipe( map(data => data.projectDto), catchError(this.logger.error));
},
catchError(err => this.logger.error('Error getting project:', err.message)),
);
}
只剩下一件事了。我们如何在组件中获取一次数据?再从路线上。
// in the component
ngOnInit() {
this.activatedRoute.data.subscribe(project => this.project = project);
// or something like this for immediate value:
// this.data = this.route.snapshot.data;
}
请注意,这将使您的页面处于“正在加载”状态,直到实际返回数据为止。如果您想并行获取数据,那是一个不同的答案,但是也可以做到。