我使用的是Angular 14和PrimeNG 14。在我的模块中,我创建了默认路由,这依赖于从解析器获取数据。我希望用户看到一个旋转器,直到数据从解析器返回。我的路由是这样设置的…
const routes: Routes = [
{
path: '',
component: MyComponent,
resolve:{
myData:MyResolver
}
}
]
在my-component.ts
文件中,我尝试像这样设置加载状态
loading = true;
constructor(private router: Router) {
console.log("subscribing ...");
this.router.events.subscribe(routerEvent => {
this.checkRouterEvent((routerEvent as RouterEvent));
});
}
checkRouterEvent(routerEvent: RouterEvent): void {
if (routerEvent instanceof NavigationStart) {
this.loading = true;
console.log("starting.");
}
if (routerEvent instanceof NavigationEnd ||
routerEvent instanceof NavigationCancel ||
routerEvent instanceof NavigationError) {
this.loading = false;
console.log("done.");
}
}
在my-component.html
文件中,我有:
<ng-template [ngIf]="loading">
<p-progressSpinner></p-progressSpinner>
</ng-template>
<ng-template [ngIf]="!loading">
...
</ng-template>
但是,我从来没有看到进度转轮。即使我关闭了端点,或者断开了与互联网的连接(我希望这样做会导致无限旋转),我的页面上也没有旋转器。我该如何解决这个问题?
编辑:正在发生的事情的演示- https://stackblitz.com/edit/primeng-progressspinner-demo-t2taze?file=src/app/app.module.ts .
在通过Resolver获取数据时显示进度旋转器
基于你的Stackblitz -example我修改了我的Stackblitz演示还有我的答案。关键事实:
- 孩子-component在路由完成之前不会被加载
- 因此父组件(而不是子组件)必须跟踪解析器的开始和完成。
- 进程微调器的HTML代码也必须是放置在父中分
App-Module:
我建议在app-module中定义整个路由,只要我们没有延迟加载的特性模块(在stackblitz的例子中,路由分布在两个模块中,因为我不想偏离Dave的解决方案太多)。
const routes: Routes = [
{
path: '',
component: ChildComponent,
resolve: {
myData: MyResolver,
},
},
];
父组件TS:
export class AppComponent implements OnDestroy {
unsubscribe = new Subject<void>();
loading = true;
constructor(private router: Router) {
console.log('subscribing ...');
this.router.events.pipe(takeUntil(this.unsubscribe))
.subscribe((routerEvent) => {
this.checkRouterEvent(routerEvent as RouterEvent);
});
}
checkRouterEvent(routerEvent: RouterEvent): void {
if (routerEvent instanceof NavigationStart) {
this.loading = true;
console.log('starting.');
}
if (routerEvent instanceof NavigationEnd ||
routerEvent instanceof NavigationCancel ||
routerEvent instanceof NavigationError) {
this.loading = false;
console.log('done.');
}
}
ngOnDestroy(): void {
this.unsubscribe.next();
}
}
父组件HTML:
router-outlet
在数据解析完成后才会加载。
<ng-template [ngIf]="loading">
<p-progressSpinner></p-progressSpinner>
</ng-template>
<router-outlet></router-outlet>
子组件TS:
在这里,来自解析器的数据可以同步访问,也就是说,当子组件被加载时,这些数据必须已经被解析过了:
resolvedData: any;
constructor(private route: ActivatedRoute) {
// Access the resolved data:
this.resolvedData = this.route.snapshot.data.myData;
// Subscribing to the Router would be worthless at this point,
// since the data is already resolved.
}
;修改你的方法,而不是"显示旋转器"。从一开始就显示它,然后在加载完成时隐藏它。看一下这个工作的stackblitz示例。
这可以使用服务来完成,在示例中我称之为loaderService
,主要的变化是您的旋转器必须在app.component
中,然后使用服务方法showLoader
和hideLoader
。这种方法的一个优点是在整个应用程序中只使用一个旋转器。
(我删除了我认为没有必要解释答案的部分代码)
app.component.html h5> app.component.ts h5> 实现它,你只需随意调用你的加载器:
my.component.ts h5> loader.service.ts h5> p>这是一个非常基本的例子,它应该会引导你。
一个复杂的当然会考虑隐藏背景内容,而加载(例如在路由之间),也会考虑一个更好看的加载器,如设置position: fixed
,居中,也许使用模糊的内容。
这是我在项目中经常使用的方法。showLoader
调用通常由我用于导航的另一个服务触发。