14

ngFor我需要在填充和显示列表时对其进行动画处理。每个元素都应该有一个过渡,让我们说这样的话。

我怎样才能做到这一点?

4

2 回答 2

14

它有一些问题,因为ngFor一些多余的添加/删除会导致项目被动画化,这不应该:

import {Component} from 'angular2/core';
import { Component, Directive, OnDestroy, Input } from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `<div (click)="$event.preventDefault()">
        <button type="button" (click)="pushItem()">Push</button>
        <button type="button" (click)="removeItemLast()">Remove Last</button><br/>
        <button type="button" (click)="unshiftItem()">Unshift</button>
        <button type="button" (click)="removeItemFirst()">Remove First</button><br/>
        <ul>
          <li class="my-animation" *ngFor="#item of items">
            {{item.title}}
          </li>
        </ul>
      </div>`
})
export class AppComponent {
  private count:number = 1;
  public items: Array<any>;
  constructor() { 
    console.clear(); 
    this.items = [];
    this.items.push(this.newItem());
    this.items.push(this.newItem());
    }
    pushItem() {
        this.items.push(this.newItem());
    },
    removeItemLast() {
      if(this.items.length > 0) this.items.splice(this.items.length - 1, 1);
    },
    unshiftItem() {
        this.items.unshift(this.newItem());
    },
    removeItemFirst() {
      if(this.items.length > 0) this.items.splice(0, 1);
    },
    newItem() {
      return {title: 'Item' + this.count++};
    }

}
@keyframes MyAnimation {
  0% {
    padding-left: 100px;
  }
  100% {
    padding-left: 0px;
  } 
}

.my-animation {
  animation: MyAnimation 1s;
}

来自https://github.com/angular/angular/issues/7239的Plunker 示例 (RC.x)演示了该问题。

更新

这是很久以前修复的

在 stackblitz 上工作Demo

于 2016-05-13T18:59:14.897 回答
8

现在有Angular 动画系统指南。如果我们想做一些花哨的事情,这很有帮助,比如只为组件初始化后添加的元素做动画,而不是已经存在的元素。我已经修改了以前的答案以使用 Angular 2 方式。

Plunker:http ://plnkr.co/edit/NAs05FiAVTlUjDOZfEsF?p=preview

import {
    Component,
    trigger, transition, animate, style, state
} from '@angular/core';

@Component({
    selector : 'my-app',
    animations: [
        trigger('growShrinkStaticStart', [
            state('in', style({ height: '*', 'padding-top': '*', 'padding-bottom': '*', 'margin-top': '*', 'margin-bottom': '*' })),
            transition('* => void', [
                style({ height: '*', 'padding-top': '*', 'padding-bottom': '*', 'margin-top': '*', 'margin-bottom': '*' }),
                animate("0.5s ease", style({ height: '0', 'padding-top': '0', 'padding-bottom': '0', 'margin-top': '0', 'margin-bottom': '0' }))
            ]),
            transition('void => false', [
                /*no transition on first load*/
            ]),
            transition('void => *', [
                style({ height: '0', 'padding-top': '0', 'padding-bottom': '0', 'margin-top': '0', 'margin-bottom': '0' }),
                animate("0.5s ease", style({ height: '*', 'padding-top': '*', 'padding-bottom': '*', 'margin-top': '*', 'margin-bottom': '*' }))
            ])
        ])
    ],
    template : `<div (click)="$event.preventDefault()">
        <button type="button" (click)="pushItem()">Push</button>
        <button type="button" (click)="removeItemLast()">Remove Last</button><br/>
        <button type="button" (click)="unshiftItem()">Unshift</button>
        <button type="button" (click)="removeItemFirst()">Remove First</button><br/>
        <ul style="background: light-blue">
          <li *ngFor="let item of items" 
          [@growShrinkStaticStart]="animationInitialized.toString()" 
          (@growShrinkStaticStart.done)="animationInitialized = true"
          style="background-color:pink; border:1px dashed gray; overflow:hidden">
            <h3>{{item.title}}</h3><p>{{item.description}}</p>
          </li>
        </ul>
        <div>Footer</div>
      </div>`
})
export class AppComponent
{
    private count: number = 1;
    public items: Array <{ title: string, description: string }> ;
    private animationInitialized: boolean = false;

    constructor() {
        this.items = [];
        this.items.push(this.newItem());
        this.items.push(this.newItem());
    }

    pushItem() {
        this.items.push(this.newItem());
    }

    removeItemLast() {
        if (this.items.length > 0)
            this.items.splice(this.items.length - 1, 1);
    }

    unshiftItem() {
        this.items.unshift(this.newItem());
    }

    removeItemFirst() {
        if (this.items.length > 0)
            this.items.splice(0, 1);
    }

    newItem() {
        let d: string = "";
        let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ    abcdefghijklmnopqrstuvwxyz0123456789 . ! ? ";

        for (let i = 0; i < Math.floor(Math.random() * 50000); i++)
            d += possible.charAt(Math.floor(Math.random() * possible.length));

        return { title : 'Item' + this.count++, description: d };
    }
}
于 2017-02-14T18:21:06.483 回答