Angular:ChangeDetection 干扰 HostBinding

问题描述

我正在尝试基于此想法实现 Animate On Scroll 库/帮助程序 Wizdm Genesys

我有一个服务,当元素与视口相交时,它会发出一个 IntersectionInfo(IsIntersecting、Direction、IsEntering 等)对象。

订阅它,如果元素正在进入视口,我会触发进入动画。

它工作正常除非我在包含该元素或其任何父元素的任何组件上使用 ChangeDetection.OnPushdetectChanges() 没有修复它。

奇怪的是变量正在改变,我可以在开发人员工具中看到它,但它没有触发动画。

使用滚动动画库的组件(HelloComponent.html):

<button mat-button color="primary" (click)="_replay = !_replay" >Primary</button>


<ng-container *ngFor="let item of items; let idx = index">

  <div class="item-container" myAos [animate]="_replay">
    <div class="item">
      {{item}}
    </div>
  </div>

</ng-container>

在 AosComponnent 中,我使用 selector: '[myAos]',因此它可以像指令一样使用。

这是 AosComponent

@Component({
  selector: '[myAos]',template: `
    <!-- H5 is just for testing info -->
    <h5>{{ trigger | json }}</h5>
    <ng-content></ng-content>
  `,styleUrls: ['./aos.component.scss'],animations: [
    trigger('aosAnimate',[
      state('idle-bumpIn',style({ opacity: 0 })),transition(
        '* => bumpIn',[
          style({ transform: 'scale(0.5)',opacity: 0 }),animate(
            '{{timing}} {{delay}} cubic-bezier(.8,-0.6,0.2,1.5)',style({ transform: 'scale(1)',opacity: 1 })
          )
        ],{ params: { timing: '500ms',delay: '' } }
      ),// None
      state('none',style('*')),state('idle-none',style('*'))
    ])
  ]
})
export class AosComponent implements OnInit {
  @Input('debounce') _debounce = 0;
  @Input('rootMargin') _rootMargin = '0px';
  @Input('root') _root: HTMLElement | undefined = undefined;
  @Input('threshold') _threshold: number = 0;
  @Input('delaySecs') _delay: number = 0.25;
  @Input('durationSecs') _duration: number = 0.5;
  private destroy$ = new Subject();

  @HostBinding('@aosAnimate')
  public trigger: any = 'none';


  @input()
  set animate(trgr: boolean) {
    this.trigger = !trgr
      ? 'idle-bumpIn'
      : {
          value: 'bumpIn',params: {
            timing: `${this._duration}s`,delay: `${this._delay}s`
          }
        };
    this._cd.detectChanges();

    console.log('animate Input',trgr,this.trigger);
  }

  //-----------------------------------------------------//

  constructor(
    private _element: ElementRef,private renderer: Renderer2,private _scroll: IntersectionService,private _cd: ChangeDetectorRef
  ) {} //ctor

  //-----------------------------------------------------//

  ngOnInit(): void {
    // const me = this

    this._scroll
      .observeIntersection(
        this._element,this._threshold,this._root,this._rootMargin
      )
      .pipe(takeuntil(this.destroy$))
      .subscribe(info => {
        this.animate = info.isEntering;
        console.log('observeIntersection',info.isEntering);
        this._cd.detectChanges();
      });
  } //ngOnInit

  //-----------------------------------------------------//

  ngOnDestroy() {
    this.destroy$.next();
  } //ngOnDestroy

  //-----------------------------------------------------//
  
} //Cls

如果我从 @input() animate 内部将 HelloComponent 设置为 true,它始终有效。 如果我将 @input() animatesubscribe 设置为 true,它仅在我从 changeDetection: ChangeDetectionStrategy.OnPush

删除 HelloComponent 时才有效

HelloComponent.ts

@Component({
  selector: 'hello',templateUrl: './hello.component.html',styleUrls: ['./hello.component.scss']
  // changeDetection: ChangeDetectionStrategy.OnPush  <--- this is the problem
})
export class HelloComponent {
  _replay = false;
  items = ['item 1','item 2','item 3','item 4','item 5'];
}

此处为 StackBlitz:My Stackblitz

有什么想法吗???

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)