[英]@ViewChild is undefined
我正在嘗試使用*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
,錯誤就會消失。 但是,我真的希望此功能可以在不需要時銷毀元素。
我在這個答案中看到你可以在@ViewChild
上使用 setter 所以我實現了它,但是沒有成功......
private privAudioPlayer: ViewContainerRef;
@ViewChild('audioPlayer') set audioPlayer(audioPlayer: ViewContainerRef) {
this.privAudioPlayer = audioPlayer;
console.log('audioPlayer set called >> ', audioPlayer, this.privAudioPlayer);
};
...然而,這總是輸出audioPlayer set called >> undefined undefined
我也試過拆分this.conversationIsRunning = true;
從其當前位置並放入各種不同的 ng 生命周期鈎子,然后也將ngOnChanges
更改為其他生命周期鈎子也無濟於事。
我必須等到下一幀還是什么? 為什么那個set audioPlayer
mutator 收到undefined
?
在第一個代碼示例中,您應該使用ngAfterViewInit()
而不是ngOnChanges()
。
問題是作為一個動態元素,在組件初始化時該元素不存在,因此使用未定義的 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';
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.