我尝试使用*ngIf切换@ViewChild元素,然后调用本机事件。
这是我的html元素,用#audioPlayer装饰,这样我就可以通过@ViewChild提取元素。
<audio
#audioPlayer
*ngIf="conversationIsRunning"
[src]='activeConversation?.clips[activeConversation.activeClipId].audio.blob'
(ended)="audioComplete($event)"
autoplay controls preload="auto" >
</audio>在我的打字稿中,我有以下内容:
@ViewChild('audioPlayer') audioPlayer;
private conversationIsRunning: boolean;
ngOnInit() {
this.conversationIsRunning = false;
}
ngOnChanges() {
console.log("ngOnChanges");
this.conversationIsRunning = true;
console.log(this.audioPlayer); // undefined
this.audioPlayer.nativeElement.play(); // error
}如果我从audio元素中删除*ngIf,这个错误就会消失。然而,我真的希望这个功能在元素在我不需要它的时候被销毁。
我在this answer中看到可以在@ViewChild上使用setter,所以我实现了它,但是没有成功……
private privAudioPlayer: ViewContainerRef;
@ViewChild('audioPlayer') set audioPlayer(audioPlayer: ViewContainerRef) {
this.privAudioPlayer = audioPlayer;
console.log('audioPlayer set called >> ', audioPlayer, this.privAudioPlayer);
};...however这将始终输出audioPlayer set called >> undefined undefined
我还尝试将this.conversationIsRunning = true;从其当前位置拆分,并将其放入各种不同的ng生命周期钩子中,然后也将ngOnChanges更改为其他生命周期钩子,但都无济于事。
我是不是要等到下一帧或者别的什么?为什么set audioPlayer赋值函数接收undefined
发布于 2017-02-14 17:25:48
在第一个代码示例中,您应该使用ngAfterViewInit()而不是ngOnChanges()。
发布于 2019-11-14 20:09:28
问题是,作为一个动态元素,该元素在组件初始化时并不存在,因此视图子元素是用一个未定义的ElementRef创建的。
这里有几个解决方案。
如果你运行Angular 8,你可以简单地告诉它这个元素不是静态的,当它存在时,视图子元素将收到ElementRef:
@ViewChild('audioPlayer', { static: false }) audioPlayer: ElementRef;在Angular 8之前,最好的方法是将条件元素放在一个子组件中,并将任何需要的数据作为输入参数传入:
<app-audio *ngIf="conversationIsRunning"> </app-audio>该子组件具有如下模板:
<audio #audioPlayer [src]='activeConversation?.clips[activeConversation.activeClipId].audio.blob'
(ended)="audioComplete($event)"
autoplay controls preload="auto" >
</audio>您的事件处理程序将位于子组件的代码中,并且您可以公开一个方法,该方法将被调用以响应父组件中的ngChanges。如果您需要与父级通信,也可以发布事件。元素始终存在于子组件中,因此ElementRef将始终有效。
最后,您也可以只切换样式显示属性。组件始终存在于DOM中,并且视图子对象将始终具有有效的ElementRef。显然,它总是使用资源并导致负载开销,无论您是否显示它:
<audio
#audioPlayer
[style.display]="conversationIsRunningDisplay()" [src]='activeConversation?.clips[activeConversation.activeClipId].audio.blob'
(ended)="audioComplete($event)"
autoplay controls preload="auto" >
</audio>你背后的代码是这样的:
@ViewChild('audioPlayer') audioPlayer;
private conversationIsRunning: boolean;
ngOnInit() {
this.conversationIsRunning = false;
}
ngOnChanges() {
console.log("ngOnChanges");
this.conversationIsRunning = true;
console.log(this.audioPlayer); // undefined
this.audioPlayer.nativeElement.play(); // error
}
public conversationIsRunningDisplay() {
if (this.conversationIsRunning) {
return 'block';
}
return 'none';
}https://stackoverflow.com/questions/42218239
复制相似问题