@ViewChild 裝飾器
基本概念
@ViewChild
是一個裝飾器,可以在 DOM 中獲取包含特定模板變量或元件的元素。它用於選擇在元件內的 template,並使這些元素在元件的 class 中可用。
基本語法
@ViewChild(selector, { static?: boolean }) name: ElementRef<Type>;
selector:可以是 component、directive、template reference variable(字串)或 TemplateRef,但不能是 CSS class。
static:可選參數,決定查詢結果什麼時候解析。
static: true
- 在ngOnInit
中可用。static: false
(默認值)- 在ngAfterViewInit
中可用。
name:元件類中用來存儲查詢結果的屬性名。
Type:選擇器獲取的元素類型。
使用範例
使用 component 作為 selector
當 selector 是元件類型時,@ViewChild
會在模板中找到該元件的第一個實例,並把這個實例儲存在命名變量中。
@ViewChild(ButtonComponent) button?: ButtonComponent;
這樣就可以在 component class 中通過 button
屬性與 ButtonComponent
的實例進行交互。
使用模板變量名作為選擇器
另一個常見用法是把 selector 設定成字串,這個字串是模板變量名(不帶 #
符號)。
例如,假設模板中有:
<form (ngSubmit)="onSubmit(titleInput.value, textInput.value)" #form>
<!-- 表單內容 -->
</form>
在元件類中可以這樣獲取:
@ViewChild('form') formContent?: ElementRef<HTMLFormElement>;
這告訴 Angular 應該在模板中找帶有 #form
的元素,並把該元素存進 formContent
中。
ElementRef 與泛型
ElementRef
是一個泛型類,它是 Angular 對原生 DOM 元素的包裝。通過泛型參數,我們可以指定被包裝元素的類型,使 TypeScript 能夠提供更好的類型檢查和智能提示。
所以需要額外的訊息來知道被包裹住的值的型別。所以在後面接的是 selector 選擇的值的類型,放在 <>
中,在這個例子中是 HTMLFormElement
要訪問實際的 DOM 元素,需要通過 .nativeElement
屬性:
this.formContent?.nativeElement.reset();
放在 onSubmit() 裡面,在表單被送出的時候會清空內容。
生命週期注意事項
@ViewChild
引用的元素在元件初始化時(構造函數中)還無法訪問根據
static
參數的不同,可以在ngOnInit
(當static: true
)或ngAfterViewInit
(當static: false
)生命週期鉤子中訪問
ngAfterViewInit() {
// 這裡可以安全地訪問 ViewChild 元素
if (this.formContent) {
console.log(this.formContent.nativeElement);
}
}
實際應用範例
清空表單:
@ViewChild('form') formContent?: ElementRef<HTMLFormElement>;
onSubmit(title: string, text: string) {
// 處理表單提交邏輯
// 重置表單
this.formContent?.nativeElement.reset();
}
注意事項:
不能向 selector 傳遞 CSS 選擇器,如
.control
使用模板變量名作為選擇器時不需要帶
#
符號如果元素可能不存在,應使用可選屬性(
?
)來避免錯誤還有 @ViewChildren 這個變體
可以加上 private:
@ViewChild('form') private formContent?: ElementRef<HTMLFormElement>;
在 Angular 17+,可以改成用 viewChild(),會給你 Signal value。
private formContent = viewChild<ElementRef<HTMLFormElement>>('form')
this.formContent()?.nativeElement.reset()
不想用問號的話可以用 .required
方法
private formContent = viewChild.required<ElementRef<HTMLFormElement>>('form')
Last updated