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都是没法获取到的

还有其余细节?欢迎评论补充,我会尽可能完善。

相关文章
相关标签/搜索