熟悉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都是没法获取到的
还有其余细节?欢迎评论补充,我会尽可能完善。