如何实现指定延迟后显示Angular路由配置加载器并避免闪烁?
解决方案
你的问题核心在于原方案的delay(250)会延迟所有路由事件的处理——哪怕加载在250ms内完成,RouteConfigLoadStart和RouteConfigLoadEnd事件都会被推迟250ms后依次处理,导致加载器短暂显示后立刻隐藏,出现闪烁。
以下是修正后的实现,确保仅当路由配置加载超过250ms时才显示加载器:
TypeScript 代码实现
import { timer, race, of } from 'rxjs'; import { filter, switchMap, map, take, distinctUntilChanged, startWith } from 'rxjs/operators'; import { Router, RouteConfigLoadStart, RouteConfigLoadEnd } from '@angular/router'; // ... 组件类内部 readonly isLoadingRouteConfig$ = this.router.events.pipe( // 只监听路由配置加载的开始和结束事件 filter(ev => ev instanceof RouteConfigLoadStart || ev instanceof RouteConfigLoadEnd), switchMap(ev => { if (ev instanceof RouteConfigLoadStart) { // 启动250ms定时器,同时监听加载结束事件:谁先触发就用谁的结果 return race( // 250ms后发出true(显示加载器) timer(250).pipe(map(() => true)), // 加载结束时立即发出false(不显示加载器),并只取第一个事件 this.router.events.pipe( filter(endEv => endEv instanceof RouteConfigLoadEnd), map(() => false), take(1) ) ); } else { // 加载结束事件触发时,直接发出false return of(false); } }), // 避免重复发送相同状态 distinctUntilChanged(), // 初始状态设为false startWith(false) );
逻辑说明
- 事件过滤:只关注
RouteConfigLoadStart和RouteConfigLoadEnd两个关键事件 - 竞争机制:当加载开始时,同时启动两个流:
- 一个250ms后触发的定时器,用于触发加载器显示
- 一个监听加载结束事件的流,用于取消加载器显示
- 状态去重:通过
distinctUntilChanged避免重复发送相同的加载状态,减少不必要的视图更新 - 初始状态:用
startWith(false)确保页面初始时不显示加载器
HTML 模板保持不变
@if (isLoadingRouteConfig$ | async) { <app-loader /> }
这样修改后,无论是页面跳转还是刷新,只要路由配置加载在250ms内完成,加载器就不会显示;只有当加载耗时超过250ms时,才会触发加载器展示,彻底解决闪烁问题。
内容的提问来源于stack exchange,提问作者Chris Barr
相关产品推荐
相关产品推荐

