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

如何使用RxJs改造组件实现防重复点击动画控制

用RxJS实现Angular组件防重复点击动画控制

核心思路

利用RxJS的exhaustMap操作符处理点击流,确保只有当上一次动画完成后,才会响应下一次点击。这种方式无需手动维护isChildAnimationComplete状态,完全通过响应式流控制逻辑。

改造步骤

1. 父组件(MeetingObjectComponent)修改

导入必要的RxJS工具和操作符,用Subject捕获点击事件,结合子组件的动画完成信号构建响应式流:

import { Component, Input, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { Meeting } from './path-to-meeting-type';
import { Subject, exhaustMap, take, tap, startWith, Subscription } from 'rxjs';
import { ChatComponent } from './chat.component';

@Component({
  selector: 'app-meeting-object',
  templateUrl: './meeting-object.component.html',
  styleUrls: ['./meeting-object.component.css'],
  animations: [
    trigger('highlightDim', [...])
  ]
})
export class MeetingObjectComponent implements OnInit, OnDestroy {
  @Input() public meetingData: Meeting | undefined;
  @ViewChild(ChatComponent) chatComponent!: ChatComponent;

  public isExpanded: boolean = false;
  private click$ = new Subject<void>();
  private subscription?: Subscription;

  ngOnInit(): void {
    // 将子组件的动画完成事件转成Observable,初始状态允许点击
    const animationComplete$ = this.chatComponent.animationComplete.pipe(
      startWith(null)
    );

    // 用exhaustMap忽略动画未完成时的重复点击
    this.subscription = this.click$.pipe(
      exhaustMap(() => animationComplete$.pipe(
        take(1), // 仅取一次动画完成信号
        tap(() => {
          this.isExpanded = !this.isExpanded;
        })
      ))
    ).subscribe();
  }

  ngOnDestroy(): void {
    // 清理订阅避免内存泄漏
    this.subscription?.unsubscribe();
    this.click$.complete();
  }
}

2. 父组件模板修改

将原来的(click)="expand()"替换为触发Subject的next()方法:

<div class="meeting" (click)="click$.next()" [@highlightDim]="isExpanded">
</div>
<app-chat
  [isExpanded]="isExpanded"
  (animationComplete)="$event"
></app-chat>

3. 子组件(ChatComponent)保持不变

子组件无需修改,继续通过animationComplete事件发送动画完成信号:

@Component({
  selector: 'app-chat',
  templateUrl: './chat.component.html',
  styleUrls: ['./chat.component.css'],
  animations:[trigger('openClose', [...])]  
})
export class ChatComponent {
  @Input() isExpanded: boolean | undefined;
  @Output() animationComplete = new EventEmitter<null>();
}

关键逻辑说明

  • exhaustMap操作符:当内部Observable(等待动画完成的流)未完成时,会忽略所有新的点击事件,彻底解决重复点击触发多次动画的问题。
  • startWith(null):确保组件初始化时允许第一次点击,因为此时还没有任何动画完成信号。
  • 订阅清理:组件销毁时取消订阅并完成Subject,避免内存泄漏。

内容的提问来源于stack exchange,提问作者JackFord

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:43:15