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

Angular动画仅触发一次的原因及解决方案

Angular动画:预加载正常但手动添加项无渲染的问题解决

我之前一直没试过Angular Animation,现在开始用了,理论上很认可它,但碰到了费解的异常行为。

原动画配置如下:

animations: [
    trigger('enterAnimation', [
      transition(':enter', [
        query(':self, td', [
          style({ transform: 'translateX(100%)', opacity: 0 }),
          stagger(100, [
            animate(
              '500ms',
              style({
                transform: 'translateX(0)',
                opacity: 1,
                'overflow-x': 'hidden',
              })
            ),
          ]),
        ]),
      ]),
    ]),
trigger('rowAnimations', [ // 注:必须加这个,否则手动添加的项无法渲染
  transition(':enter', [
    style({ transform: 'translateX(100%)', opacity: 0 }),
    query(':self', [
      animate(
        '500ms',
        style({
          transform: 'translateX(0)',
          opacity: 1,
          'overflow-x': 'hidden',
        })
      ),
    ]),
  ]),
  transition(':leave', [
    query(':self', [
      style({
        transform: 'translateX(0)',
        opacity: 1,
        overflow: 'hidden',
        width: '100%',
        height: '*',
      }),
      animate('500ms', style({ transform: 'translateX(50%)', opacity: 0 })),
    ]),
  ]),
]),
],

触发器enterAnimation在预加载数据时表现完美,首次加载项时动画会按顺序延迟执行。但如果不额外加rowAnimations触发器的:enter过渡,手动添加的项根本渲染不出来。


解决方案

首先调整模板结构,给表格绑定一个触发器,并用ng-container包裹循环的行:

<table [@tableAnimations]="items.length" id="customers">
  <tr>
    <th>Name</th>
    <th>Country</th>
  </tr>
  <ng-container *ngFor="let o of items; let i = index">
    <tr class="data" [@rowAnimations]>
      <td>{{ o.Name }}</td>
      <td>{{ o.Country }}</td>
    </tr>
  </ng-container>
</table>

然后更新动画配置,给表格新增触发器并配合过渡规则实现 stagger 效果:

animations: [
  trigger('tableAnimations', [
    transition('* <=> *', [
      query('@rowAnimations', [stagger(100, [animateChild()])]),
    ]),
  ]),
  trigger('rowAnimations', [
    transition(':enter', [
      style({ transform: 'translateX(100%)', opacity: 0 }),
      animate(
        '500ms',
        style({
          transform: 'translateX(0)',
          opacity: 1,
          'overflow-x': 'hidden',
        })
      ),
    ]),
    transition(':leave', [
      style({
        transform: 'translateX(0)',
        opacity: 1,
        overflow: 'hidden',
        width: '100%',
        height: '*',
      }),
      animate('500ms', style({ transform: 'translateX(50%)', opacity: 0 })),
    ]),
  ]),
],

原理说明

核心是给容器(这里是表格)添加一个超出:enter选择器范围的触发器,绑定数组长度是最简便的触发方式。* <=> *过渡规则表示绑定到触发器的任意值变化都会触发动画,通过animateChild()可以调用子元素的rowAnimations动画,再配合stagger就能实现行动画的顺序延迟效果。如果没有这个过渡规则,所有行的动画会同时触发,无法达到 stagger 的顺序延迟效果。

内容的提问来源于stack exchange,提问作者ak.leimrey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:17:07