更改组件内部和外部 Angular 组件的输入之间的差异(+动画)

问题描述 投票:0回答:1

我制作了一个手风琴组件(Angular18),其主体内容延迟加载,并且打开和关闭的动画流畅。 因此,当我从内部切换它时(通过单击标题),它工作得很好, 但是当我从外面切换它时 - 它不能顺利打开(但可以顺利关闭)。

这是堆栈闪电战: https://stackblitz.com/edit/stackblitz-starters-rjsmkv

这种行为有什么意义?我对 Angular 动画很陌生..

尝试用输入替换模型 - 同样的事情。由于内容大小不同,具有 maxheight 的 CSS 动画不够好。

angular signals accordion angular-animations angular-signals
1个回答
0
投票

信号的

toObservable
,似乎重新触发了
delayedIsOpen
的流,这反过来又重新创建了if条件
@if (delayedIsOpen | async) {
内的元素,并再次创建了元素
<ng-container *ngTemplateOutlet="accordionBodyRef" />
,这似乎弄乱了动画。

我不确定您为什么需要这种延迟,但消除延迟可以解决问题。

HTML

<div
  class="accordion"
  [ngStyle]="{ '--transiton-time': transitionTime + 'ms' }"
>
  <div class="accordion-head">
    <div class="top-side top-side_left" (click)="toggle()">
      <ng-content select="[topLeft]" />
    </div>
  </div>
  <div
    class="main-content"
    [@content]="
      isOpen()
        ? { value: 'visible', params: { transitionParams } }
        : { value: 'hidden', params: { transitionParams } }
    "
  >
    <ng-container *ngTemplateOutlet="accordionBodyRef" />
  </div>
</div>

TS:

import {
  animate,
  state,
  style,
  transition,
  trigger,
} from '@angular/animations';
import {
  ChangeDetectionStrategy,
  Component,
  input,
  model,
  ContentChild,
  TemplateRef,
} from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { delay, of, switchMap } from 'rxjs';

@Component({
  selector: 'accordion',
  templateUrl: './accordion.component.html',
  styleUrl: './accordion.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
  animations: [
    trigger('content', [
      state(
        'hidden',
        style({
          height: '0',
          visibility: 'hidden',
        })
      ),
      state(
        'visible',
        style({
          height: '*',
          visibility: 'visible',
        })
      ),
      transition('visible <=> hidden', [animate('{{transitionParams}}')]),
      transition('void => *', animate(0)),
    ]),
  ],
})
export class AccordionComponent {
  isOpen = model<boolean>(false);

  transitionTime = 500;
  transitionParams = `${this.transitionTime}ms linear`;

  // delayedIsOpen = toObservable(this.isOpen)
  //   .pipe
  //   // switchMap((open) =>
  //   //   open ? of(open) : of(open).pipe(delay(this.transitionTime))
  //   // )
  //   ();

  @ContentChild('accordionBody', { read: TemplateRef })
  accordionBodyRef: TemplateRef<unknown> | null = null;

  toggle(): void {
    this.isOpen.update((value) => !value);
  }
}

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.