Angular2視圖操做之ViewChild&ViewChildren

熟悉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都是沒法獲取到的

還有其餘細節?歡迎評論補充,我會盡可能完善。

相關文章
相關標籤/搜索