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

使用Router Outlet时,如何在组件切换间添加加载动画?

在Angular路由导航时添加加载动画(Router Outlet场景)

针对你提到的注册页面切换组件需8秒、使用Router Outlet导航的场景,以下是两种实用实现方案:

方案一:监听路由导航事件,全局显示加载动画

这种方式适用于路由切换过程(包括懒加载chunk下载、组件初始化)的等待状态,在根组件中统一控制加载界面的显示。

步骤1:在根组件中订阅路由事件

在app.component.ts中注入Router,监听导航开始/结束/失败/取消事件,维护加载状态:

import { Component } from '@angular/core';
import { Router, NavigationStart, NavigationEnd, NavigationError, NavigationCancel } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  isLoading = false;

  constructor(private router: Router) {
    this.router.events.subscribe(event => {
      // 导航开始时显示加载动画
      if (event instanceof NavigationStart) {
        this.isLoading = true;
      }
      // 导航结束、失败或取消时隐藏加载动画
      if (event instanceof NavigationEnd || event instanceof NavigationError || event instanceof NavigationCancel) {
        this.isLoading = false;
      }
    });
  }
}

步骤2:在根组件模板中添加加载动画

在Router Outlet旁插入加载元素,用*ngIf根据状态控制显示:

<!-- 全局加载覆盖层 -->
<div *ngIf="isLoading" class="loading-overlay">
  <div class="spinner"></div>
</div>

<!-- 路由出口 -->
<router-outlet></router-outlet>

步骤3:添加加载动画样式

在app.component.css中定义加载动画的样式:

.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255,255,255,0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
}

.spinner {
  width: 50px;
  height: 50px;
  border: 5px solid #f3f3f3;
  border-top: 5px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

方案二:使用路由Resolve守卫,组件内显示加载状态

如果延迟是因为目标组件需要加载大量数据(而非路由本身),可以用Resolve守卫在路由激活前预加载数据,同时在组件内显示加载动画。

步骤1:创建Resolve数据加载服务

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class DataResolveService implements Resolve<any> {
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    // 模拟8秒的数据加载过程
    return of({ content: '目标组件所需数据' }).pipe(delay(8000));
  }
}

步骤2:配置路由关联Resolve

在路由配置中指定该Resolve,确保数据加载完成后才激活组件:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { TargetComponent } from './target/target.component';
import { DataResolveService } from './data-resolve.service';

const routes: Routes = [
  {
    path: 'target',
    component: TargetComponent,
    resolve: {
      targetData: DataResolveService
    }
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

步骤3:目标组件内控制加载状态

在目标组件中获取路由解析的数据,控制加载动画的显示:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-target',
  templateUrl: './target.component.html',
  styleUrls: ['./target.component.css']
})
export class TargetComponent implements OnInit {
  isLoading = true;
  componentData: any;

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    // 获取路由解析完成的数据
    this.componentData = this.route.snapshot.data['targetData'];
    this.isLoading = false;
  }
}

目标组件模板:

<div *ngIf="isLoading" class="component-loading">
  <div class="spinner"></div>
  <p>数据加载中...</p>
</div>

<div *ngIf="!isLoading" class="component-content">
  <h2>组件内容</h2>
  <p>{{ componentData.content }}</p>
</div>

补充说明

  • 如果是懒加载模块导致的延迟,方案一的路由事件监听会自动覆盖,因为懒加载chunk下载时NavigationStart触发,直到chunk加载完成才会触发NavigationEnd。
  • 可以根据需求自定义加载动画的样式,比如更换spinner图标、添加文字提示等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:17:55