当你在 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">