@ViewChild()
decorator 一開始是在存取 child component 時學到的,事實上 @ViewChild()
還有其他使用方法。
Version
Node.js 8.9.3
Angular CLI 1.6.2
Angular 5.2
Component
使用 @ViewChild()
存取 child component。
-
counter
初始值為2
- 按
+
則counter
+ 1,按-
則counter
-1
Architecture
-
AppComponent
負責處理<button/>
;CounterComponent
負責顯示counter
-
AppComponent
相當於 parent component,CounterComponent
相當於 child component -
AppComponent
直接呼叫CounterComponent
的 method 改變counter
;AppComponent
也可直接讀取CounterComponent
的 property
Implementation
AppComponent
app.component.html
<button (click)="onAddOneClick()">+</button> <button (click)="onMinusOneClick()">-</button> <p></p> <app-counter></app-counter>
將 2 個 <button/>
留在 AppComponent
內。
counter
的顯示由 <app-counter/>
負責。
app.component.ts
import { AfterViewInit, Component, ViewChild } from '@angular/core'; import { CounterComponent } from './counter/counter.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements AfterViewInit { @ViewChild(CounterComponent) private counterComponent: CounterComponent; ngAfterViewInit(): void { console.log(this.counterComponent.counter); } onAddOneClick() { this.counterComponent.addOne(); } onMinusOneClick() { this.counterComponent.minusOne(); } }
10 行
@ViewChild(CounterComponent) private counterComponent: CounterComponent;
Angular 允許我們在 parent component 透過 @ViewChild()
decorator 宣告 child component,藉此存取 child component 的 public field 與 method。
@ViewChild()
第一個參數傳入 child component 的型別。
第 9 行
export class AppComponent implements AfterViewInit { ngAfterViewInit(): void { console.log(this.counterComponent.counter); } }
若要透過 @ViewChild()
存取 child component 的 public field,則必須在 ngAfterViewInit()
lifecycle hook 才可抓的到,不可以在 ngOnInit()
。
17 行
onAddOneClick() { this.counterComponent.addOne(); }
若要透過 @ViewChild()
存取 child component 的 public method,則無此限制。
CounterComponent
counter.component.html
{{ counter }}
負責顯示 counter
。
counter.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-counter', templateUrl: './counter.component.html', styleUrls: ['./counter.component.css'] }) export class CounterComponent { counter = 2; addOne() { this.counter++; } minusOne() { this.counter--; } }
沒有特別的部分需要講解。
當 parent component 要存取 child component 時,使用 @ViewChild()
宣告 child decorator,public field 可在 ngAfterViewInit()
存取,public method 則無此限制
Directive
當使用 directive 套用在 HTML 上時,可以藉由 @ViewChild()
取得 directive 的物件實體,藉此控制 directive。
Implementation
ChangeColorDirective
change-color.directive.ts
import { AfterViewInit, Directive, ElementRef } from '@angular/core'; @Directive({ selector: '[appChangeColor]' }) export class ChangeColorDirective implements AfterViewInit { constructor(private elementRef: ElementRef) { } ngAfterViewInit(): void { this.elementRef.nativeElement.style.color = 'red'; } change(changedColor: string) { this.elementRef.nativeElement.style.color = changedColor; } }
使用 Angular CLI 的 ng g d ChangeColor
建立 ChangeColor
directive。
15 行
change(changedColor: string) { this.elementRef.nativeElement.style.color = changedColor; }
ChangeColor
directive 提供了 change()
修改 color
。
AppComponent
app.component.html
<p appChangeColor>{{ title }}</p> <p></p> <button (click)="onChangeColorClick()">Change Color</button>
<p>
套用了 ChangeColor
directive。
app.component.ts
import { Component, ViewChild } from '@angular/core'; import { ChangeColorDirective } from './change-color.directive'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { @ViewChild(ChangeColorDirective) private changeColorDirective: ChangeColorDirective; title = 'app'; onChangeColorClick() { this.changeColorDirective.change('green'); } }
10 行
@ViewChild(ChangeColorDirective) private changeColorDirective: ChangeColorDirective;
為了使用 ChangeColor
directive 的 change()
,特別使用 @ViewChild()
取得 ChangeColor
directive 的物件實體,如此就能使用 change()
。
DOM Element
最後一個常用的 @ViewChild()
方式,是藉由 template reference varibale 存取 DOM element。
Implementation
AppComponent
app.component.html
Name: <input type="text" #name> <p></p> <button (click)="onSubmitClick()">Submit</button> <p></p> {{ yourName }}
若要在 JavaScript 存取 HTML,傳統會使用 id
或 CSS selector,在 Angular 提出新的方法,我們可以為 HTML 加上 #
開頭的 template reference variable。
app.component.ts
import { Component, ElementRef, ViewChild } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { yourName: string; @ViewChild('name') private name: ElementRef; onSubmitClick() { this.yourName = this.name.nativeElement.value; } }
11 行
@ViewChild('name') private name: ElementRef;
使用 @ViewChild()
取得 DOM element 的物件實體,參數以字串傳入 template reference variable 的字串名稱。
注意其型別為 ElementRef
。
14 行
onSubmitClick() { this.yourName = this.name.nativeElement.value; }
如此就能在 TypeScript 藉由 @ViewChild()
所宣告的變數,存取 DOM element 物件。
Conclusion
- 傳統都只將
@ViewChild()
用在存取 child component,事實上@ViewChild()
還可以用在存取 directive 與 DOM element。
Sample Code
完整的範例可以在我的 GitHub 上找到
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。