Angular2视图操作之ViewChild&ViewChildren
熟悉Angular1.X版本的同学应该知道,Angular1.X在指令中的link函数中提供了element参数,让我们可以对元素的原生dom进行获取和操作,在新版本的Angular中,则以decorator的形式,提供了ViewChild,ViewChildren,以及对应的ContentChild和ContentChildren让我们可以获取元素的dom对象,本文讲解较为常用的ViewChild和ViewChildren这两个decorator 注意:使用时需要从@angular/core中引入ViewChild和ViewChildren ViewChild: ViewChild可以获取到当前组件视图中的单个元素,获取方式有两种: 第一种(通过模板引用变量): <main #mychild> <!-- my html content --> </main> @ViewChild('mychild') myChild : ElementRef constructor() { } ngAfterViewInit() { console.log(this.myChild) } 第二种(直接指定组件类): <my-child></my-child> @Component({ selector: 'my-child',templateUrl: './xxxxx.html' }) class ChildComponent { constructor() { } } @ViewChild() myChild : ChildComponent; ngAfterViewInit() { console.log(this.myChild) } 这两种方式有何区别呢? 区别在于,第一种方式取得的mychild变量是经过包装的,他是一个ElementRef类,其中包含了nativeElement这个属性,这个属性的值就相当于通过原生dom操作取得的element。打印结果如下图: 而如果通过第二种方式,我们需要为组件类注入ElementRef,才能够取得nativeElement,如下: //先引入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.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都是无法获取到的 还有其他细节?欢迎评论补充,我会尽量完善。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |