Angular指令注册到类上的应用

66 阅读1分钟

当你在 Angular 中创建一个指令时,每个指令实例都是一个独立的对象。AudioPlayerDirective.audioPlayers.push(this); 这行代码的作用是将当前指令实例添加到一个静态数组 audioPlayers 中。这个数组是一个类级别的属性,而不是实例级别的属性,因此它对于所有 AudioPlayerDirective 类的实例都是共享的。

通过将每个指令实例添加到这个数组中,我们创建了一个集合,其中包含了所有 AudioPlayerDirective 指令的实例。这使得我们可以在其中遍历并执行操作,例如停止所有指令实例中播放的音频。

让我们逐行注释这段代码:

import { Directive, ElementRef, HostListener, Input, Output, EventEmitter, OnDestroy } from '@angular/core';

@Directive({
  selector: '[appAudioPlayer]',
  exportAs: 'appAudioPlayer'
})
  export class AudioPlayerDirective implements OnDestroy {
    // 静态数组用于保存所有具有 AudioPlayerDirective 指令的实例
    private static audioPlayers: AudioPlayerDirective[] = [];

    private audio: HTMLAudioElement;
    private isPlaying: boolean = false;

    /** 音频地址 */
    @Input() appAudioPlayer: string;

    /** 唯一标识符 */
    @Input() appAudioPlayerId: string;

    /** 导出状态变量 */
    @Output() isPlayingChange: EventEmitter<boolean> = new EventEmitter<boolean>();

    constructor(private el: ElementRef) {
      // 创建 HTMLAudioElement 实例
      this.audio = new Audio();
      // 将当前指令实例添加到静态数组中
      AudioPlayerDirective.audioPlayers.push(this);
    }

    @HostListener('click') onClick(): void {
      if (!this.appAudioPlayer) { return; }

      // 停止所有其他指令播放的音频
      AudioPlayerDirective.audioPlayers.forEach((player: AudioPlayerDirective) => {
        if (player !== this) {
          player.pauseAudio();
        }
      });

      if (this.audio.paused) {
        this.playAudio();
      } else {
        this.pauseAudio();
      }
    }

    private playAudio(): void {
      this.audio.src = this.appAudioPlayer;
      this.audio.load();
      this.audio.play();
      this.isPlaying = true;
      this.isPlayingChange.emit(true);
    }

    pauseAudio(): void {
      this.audio.pause();
      this.isPlaying = false;
      this.isPlayingChange.emit(false);
    }

    ngOnDestroy(): void {
      // 移除当前指令实例从静态数组中
      const index = AudioPlayerDirective.audioPlayers.indexOf(this);
      if (index !== -1) {
        AudioPlayerDirective.audioPlayers.splice(index, 1);
      }
      // 停止音频播放
      this.pauseAudio();
    }
  }

使用方法

<img [src]="audioPlayer?.isPlaying ? '正在播放.gif' : '点我播放.png'" alt="" [appAudioPlayer]="audioUrl" #audioPlayer="appAudioPlayer" *ngIf="audioUrl">