首页 > 解决方案 > Angular - 如何使用查询避免初始加载动画

问题描述

我正在使用 Angular 10(但问题应该与 Angular 2+ 相同)

我有一个特定页面,需要query('.xxx')在页面加载/卸载时为多个 DOM 元素设置动画。

我想在页面加载/卸载时应用这些动画,除非这是第一次加载(用户访问网站时的第一个页面视图)。

我尝试了很多东西:

我可以使用特定的页面更改触发器来获取它,例如home => pageA, xxx => pageA,但我不想列出所有可能性......我的想法是让它使用* <=> * 或至少* => pageA:)

没有得到预期的结果......我认为这是一个常见的情况,有人可以帮助我实现这一目标吗?

我做了一个stackblitz来展示这个想法:https ://stackblitz.com/edit/angular-animation-avoid-first?file=src/app/page-a.component.ts

switch home <=> pageA 应该触发动画,但是 pageA 上的初始加载不应该......

在这里,我发布了简单的示例代码:

app.component.ts

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { animate, animateChild, query, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'my-app',
  template: `<main [@routeAnimations]="prepareRoute(outlet)">
              <router-outlet #outlet="outlet"></router-outlet>
            </main>`,
  styleUrls: [ './app.component.css' ],
  animations: [
    trigger('routeAnimations', [
      transition(':enter', []), // to try disabling first animation
      transition('* <=> *', [
        query(':leave', animateChild(), { optional: true }),
        query(':enter', animateChild(), { optional: true }),
      ]),
    ])
  ]
})
export class AppComponent  {
  public prepareRoute(outlet: RouterOutlet) {
    return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
  }
}

home.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-home',
  template: `<h1>THIS IS HOME</h1><a [routerLink]="['/']">Page A</a>`,
  styles: []
})
export class HomeComponent  {
}

页面-a.component.ts

import { Component, HostBinding } from '@angular/core';
import { Router } from '@angular/router';
import { animate, stagger, style, transition, query, trigger } from '@angular/animations';

@Component({
  selector: 'app-page-a',
  template: '<div class="red">ELEMENT</div><button (click)="changePage()">Change Page</button>',
  styles: ['div {width: 200px;height: 100px;background: #f00}'],
  animations: [
    trigger('animation', [
      transition(':enter', [
        query('.red', [
          style({opacity: 0, transform: 'translateY(-100px)'}),
          animate('500ms cubic-bezier(0.35, 0, 0.25, 1)', style({ opacity: 1, transform: 'none' }))
        ])
      ]),
      transition(':leave', [
        query('.red', [
          animate('500ms cubic-bezier(0.35, 0, 0.25, 1)', style({ opacity: 0, transform: 'translateY(-100px)' }))
        ])
      ])
    ]),
  ]
})
export class PageAComponent {
  
  @HostBinding('@animation')
  public animation;

  public constructor(private router: Router) {}

  public changePage(): void {
    this.router.navigate(['/home']);
  }
}

谢谢 !:)

标签: angularanimationtriggers

解决方案


没有办法用简单的动画 api 做到这一点。我可以向您建议的是检测当前正在发生的导航顺序,如果是第一个则禁用所有动画。
零件:

routeLoadNumber$ = this.router.events.pipe(
    filter(evt => evt instanceof NavigationEnd),
    scan((a)=> a + 1, 0)
  );

constructor(private router: Router) {}

html

<main [@routeAnimations]="prepareRoute(outlet)" [@.disabled]="(routeLoadNumber$ | async)==1">

推荐阅读