如何在Angular路由切换时为<router-outlet>添加淡入动画?
问题描述
我有如下HTML组件代码:
<section class="flex flex-col w-full h-[100vh] overflow-hidden animate__animated animate__fadeIn" > <!-- 顶部导航栏固定在顶部,不会收缩 --> <app-top-navbar class="flex-shrink-0"></app-top-navbar> <!-- 包含侧边栏和动态内容的主区域 --> <div class="h-full flex overflow-hidden"> <!-- 侧边导航栏宽度固定,不会伸缩 --> <app-side-navbar class="w-[10%] flex-shrink-0"></app-side-navbar> <!-- 可扩展且独立滚动的内容区域 --> <div class="w-full flex flex-col relative h-full overflow-y-auto"> <p class="p-3 drop-shadow-md text-gray-800 font-semibold"> {{ sectionTitle }} </p> <!-- 垂直可拉伸的居中路由容器 --> <div class="flex items-center justify-center h-full"> <router-outlet></router-outlet> </div> <!-- 位于内容区域底部的导航组件 --> <app-overview-nav [back_router_link]="back_router_link" [next_router_link]="next_router_link" ></app-overview-nav> </div> </div> </section>
当前页面加载时,整个section会执行animate__animated animate__fadeIn动画,但我希望下面这个容器:
<div class="flex items-center justify-center h-full"> <router-outlet></router-outlet> </div>
在每次路由切换时都触发animate__animated animate__fadeIn动画。我尝试直接给<router-outlet>添加这两个动画类,但没有效果。
解决方案
方法1:用Angular原生路由动画(推荐)
Angular自带路由切换动画支持,无需依赖外部类库:
- 在当前模块的
@NgModule中导入动画模块:
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ imports: [ // 其他已导入模块 BrowserAnimationsModule ] }) export class YourModule { }
- 在包裹路由的组件中定义动画逻辑:
import { trigger, transition, style, animate } from '@angular/animations'; @Component({ // 组件元数据(selector、templateUrl等) animations: [ trigger('routeFade', [ // 组件进入时的淡入动画 transition(':enter', [ style({ opacity: 0 }), animate('300ms ease-in', style({ opacity: 1 })) ]), // 组件离开时的淡出动画(可选) transition(':leave', [ animate('300ms ease-out', style({ opacity: 0 })) ]) ]) ] }) export class YourComponent { }
- 修改模板,给路由容器绑定动画触发器:
<div class="flex items-center justify-center h-full" [@routeFade]> <router-outlet></router-outlet> </div>
方法2:监听路由变化动态添加动画类
如果想用Animate.css的预设类,需要通过监听路由事件手动触发:
- 在组件中注入路由服务,监听路由切换完成事件:
import { Router, NavigationEnd } from '@angular/router'; import { ElementRef, ViewChild } from '@angular/core'; import { filter } from 'rxjs/operators'; @Component({ // 组件元数据 }) export class YourComponent { @ViewChild('routeContainer') routeContainer!: ElementRef; constructor(private router: Router) { this.router.events.pipe( filter(event => event instanceof NavigationEnd) ).subscribe(() => { // 先移除动画类避免重复触发异常 this.routeContainer.nativeElement.classList.remove('animate__animated', 'animate__fadeIn'); // 强制触发DOM重绘,确保动画能重新执行 void this.routeContainer.nativeElement.offsetWidth; // 重新添加动画类触发淡入 this.routeContainer.nativeElement.classList.add('animate__animated', 'animate__fadeIn'); }); } }
- 给路由容器添加模板引用变量:
<div #routeContainer class="flex items-center justify-center h-full"> <router-outlet></router-outlet> </div>
为什么直接加在router-outlet上没用?
<router-outlet>是Angular的占位符元素,它本身不会被渲染到最终DOM中,真正显示的是路由对应的组件。所以动画类加在它身上不会生效,必须把动画作用在它的父容器或者路由组件本身上。
内容的提问来源于stack exchange,提问作者user28273827332
相关产品推荐
相关产品推荐

