3

我有一个使用 angular 2 构建的测试应用程序,我已经成功地在路线更改之间应用了一个动画

state('default', style({
    opacity: 1,
    transform: 'scale(1) translateY(0)'
})),
transition('void <=> default', [
    style({ opacity: 0, transform: 'scale(.9) translateY(-20px)' }),
    animate('.2s')
])

但是当列表页面更改为项目页面时,我也想要不同的动画,例如单击英雄列表中的英雄,所以我这样做了

state('childActivate', style({
    opacity: 1,
    transform: 'scale(1) translateY(0)'
})),
transition('childActivate => void', [
    animate('1.2s', style({
        transform: 'scale(0.9)  translateY(-120px)',
        opacity: 0
    }))
])

在单击项目后和导航之前,我尝试将状态设置为“childActivated”:

onHeroSelected(heroEvent: Hero) {
    this.animState = "childActivate";
    this.router.navigate(['/hero-detail', heroEvent.id]);
}

但没有效果。

如何在路线之间获得多个动画?

4

1 回答 1

1

将状态设置为“childActivate”没有任何效果,因为组件在下一个更改检测步骤中被销毁,因此状态切换为 void。

这就是我解决此问题的方法:我将路线更改延迟了 1 个进一步的更改检测周期。为此,我使用了 CanDeactivate Guard,它会侦听要解决的承诺。

查看我的 plnkr: https ://embed.plnkr.co/cOeDfXCetaYuXFaZ7WeO/

在路线定义中,我添加:

canDeactivate: [CanDeactivateAfterChangeDetectionGuard]

这是 CanDeactivate Guard:

@Injectable()
class CanDeactivateAfterChangeDetectionGuard implements CanDeactivate<WaitForChangeDetection> {
  canDeactivate(component: WaitForChangeDetection): Promise<boolean> {
    return component.waitForChangeDetection();
  }
}

它适用于实现此接口的任何组件:

declare abstract class WaitForChangeDetection {
  abstract waitForChangeDetection(): Promise<boolean>;
}

我用这个接口的默认实现创建了一个基础组件

@Component({})
class WaitForChangeDetectionImpl implements AfterViewChecked, WaitForChangeDetection {
  constructor(private cdRef: ChangeDetectorRef){
    this.viewChecked$ = new Subject<void>();
  }

  viewChecked$: Subject<void>;
  waitForChangeDetection(): Promise<boolean>{
    this.cdRef.detectChanges();
    return new Promise((resolve) => this.viewChecked$.subscribe(() => resolve(true)));
  }

  ngAfterViewChecked(){
    this.viewChecked$.next();
  }
}

因此,您可以扩展此组件以提供与任何组件的防护一起使用的功能。

@Component({})
class ComponentA extends WaitForChangeDetectionImpl {
...
于 2017-03-22T10:12:19.820 回答