熟悉Angular1.X版本的同窗應該知道,Angular1.X在指令中的link函數中提供了element參數,讓咱們能夠對元素的原生dom進行獲取和操做,在新版本的Angular中,則以decorator的形式,提供了ViewChild,ViewChildren,以及對應的ContentChild和ContentChildren讓咱們能夠獲取元素的dom對象,本文講解較爲經常使用的ViewChild和ViewChildren這兩個decoratorjavascript
注意:使用時須要從@angular/core中引入ViewChild和ViewChildrenhtml
ViewChild:java
ViewChild能夠獲取到當前組件視圖中的單個元素,獲取方式有兩種:數組
第一種(經過模板引用變量):安全
<main #mychild> <!-- my html content --> </main>
@ViewChild('mychild') myChild : ElementRef constructor() { } ngAfterViewInit() { console.log(this.myChild) }
第二種(直接指定組件類):dom
<my-child></my-child>
@Component({ selector: 'my-child', templateUrl: './xxxxx.html' }) class ChildComponent { constructor() { } }
@ViewChild() myChild : ChildComponent; ngAfterViewInit() { console.log(this.myChild) }
這兩種方式有何區別呢?ide
區別在於,第一種方式取得的mychild變量是通過包裝的,他是一個ElementRef類,其中包含了nativeElement這個屬性,這個屬性的值就至關於經過原生dom操做取得的element。打印結果以下圖:函數
而若是經過第二種方式,咱們須要爲組件類注入ElementRef,纔可以取得nativeElement,以下:ui
//先引入ElementRef //import {ElementRef} from '@angular/core'; @Component({ selector: 'my-child', templateUrl: './xxxxx.html' }) class ChildComponent { constructor(public ele: ElementRef) { } }
注意,爲ChildComponent實例化ElementRef時,須要用public標識符,private的話會致使外部沒法取得該ele變量(那你就得專門爲其實現一個get方法)this
這時,咱們就能經過this.mychild.ele.nativeElement來取得其DOM元素了
ViewChildren:
對應的,ViewChildren,顧名思義是能夠得到一個視圖集合,它是一個類數組的形式,使用方式與ViewChild類似,但須要以QueryList的形式存在:
@ViewChildren(ChildComponent) myChild : QueryList<ChildComponent>; ngAfterViewInit() { console.log(this.myChild) }
QueryList是個什麼概念?
咱們看看官方文檔的解釋:
我看不懂英文,總的來講就是一個結果集,這個結果集在你的Angular應用更新完成時也隨之更新,
但裏面的結果是不能夠直接訪問和修改的(很合理)。
咱們先來看看打印出來的ViewChildren實例長啥樣:
能夠發現咱們想要的取得的結果--(_results)屬性,然而這個_results屬性是private的,咱們沒法直接取得(經實踐能夠經過mychild['_results']的方法來獲取,但這也已經超出了ts的範圍,也是不安全的作法,應該杜絕),但咱們有兩種方式能夠遍歷這個_results數組:
第一是經過mychild.forEach()方法,第二是先調用QueryList原型中的toArray()方法,接着再用數組的方式進行處理
監聽視圖變化:
假設咱們有一個由多個my-child組成列表,它能夠添加或移除my-child組件,咱們但願在my-child集合被改動時都作出迴應,此時Observable就派上用場了,QueryList爲咱們提供了一個changes的Observable:
咱們只須要訂閱它就能夠完成這個需求了:
this.mychild.changes.subscribe((data)=>{ // do something })
細節:
爲什麼是ngAfterViewInit?
注意到咱們獲取mychild都是在ngAfterViewInit的生命週期鉤子函數中進行的(生命週期的流程詳見https://www.angular.cn/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges)
這是由於mychild是在ngAfterViewInit完成後才能獲取到值,因此也能夠在ngAfterViewChecked中獲取,但前者是最快能獲取到的地方,因此在ngAfterViewInit以前的階段,好比ngOnInit,ngOnChanges都是沒法獲取到的
還有其餘細節?歡迎評論補充,我會盡可能完善。