You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现指定延迟后显示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)
);

逻辑说明

  1. 事件过滤:只关注RouteConfigLoadStart和RouteConfigLoadEnd两个关键事件
  2. 竞争机制:当加载开始时,同时启动两个流:
    • 一个250ms后触发的定时器,用于触发加载器显示
    • 一个监听加载结束事件的流,用于取消加载器显示
  3. 状态去重:通过distinctUntilChanged避免重复发送相同的加载状态,减少不必要的视图更新
  4. 初始状态:用startWith(false)确保页面初始时不显示加载器

HTML 模板保持不变

@if (isLoadingRouteConfig$ | async) {
  <app-loader />
}

这样修改后,无论是页面跳转还是刷新,只要路由配置加载在250ms内完成,加载器就不会显示;只有当加载耗时超过250ms时,才会触发加载器展示,彻底解决闪烁问题。

内容的提问来源于stack exchange,提问作者Chris Barr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:33:16