在使用Angular2+中,经常会想快速的去选择DOM上的某个元素,如果是刚上手Angular,有可能直接就使用原生DOM操作或者导入jQuery再进行DOM操作,既然都使用了Angular了,有没有更好的方法呢?答案是肯定的。
通过ElementRef
先上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import {Component, ElementRef, OnInit} from '@angular/core';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ color:string; title = 'button !';
constructor(private el:ElementRef){}
setHeight(){ this.el.nativeElement.querySelector('.btn1').style.height = '300px'; }
ngOnInit(){ this.setHeight(); }
}
|
1 2 3 4 5 6 7 8
| <h1> {{title}} </h1> <div> <button myHighlight class="btn btn1">按钮一</button> <button myHighlight class="btn">按钮二</button> <button myHighlight class="btn">按钮三</button> </div>
|
效果是这样:
上述代码中的nativeElement
其实包含的是组件中所有的DOM元素,如下图所示:
通过调用querySelector
API就能获取页面元素,需要注意的是querySelector
只返回第一个元素,当你需要选择多个元素的时候可以使用querySelectorAll
。
通过@viewChild
1 2 3 4 5 6 7 8
| <h1> {{title}} </h1> <div> <button myHighlight class="btn btn1">按钮一</button> <button myHighlight class="btn" #btn>按钮二</button> <button myHighlight class="btn">按钮三</button> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ @ViewChild('btn') btn:ElementRef;
color:string; title = 'button !';
constructor(private el:ElementRef){}
setHeight(){ this.el.nativeElement.querySelector('.btn1').style.height = '300px'; }
setWidth(){ this.btn.nativeElement.style.width = '200px'; }
ngOnInit(){ this.setHeight(); this.setWidth(); }
}
|
效果如下:
如果多个HTML元素都定义了相同的变量,使用@viewChild
时只能选择到第一个元素。
更好的方法是配合renderer2
对象提供的API去实现同样的效果,这样减少应用层与渲染层之间强耦合关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import {Component, ElementRef, OnInit, Renderer2, ViewChild} from '@angular/core';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ @ViewChild('btn') btn:ElementRef;
color:string; title = 'button !';
constructor(private el:ElementRef,private renderer2: Renderer2){}
setHeight(){ this.el.nativeElement.querySelector('.btn1').style.height = '300px'; }
setWidth(){ this.renderer2.setStyle(this.btn.nativeElement,'width','200px') }
ngOnInit(){ this.setHeight(); this.setWidth(); }
}
|
参考文章中都提到了@viewChild
配合renderer
选择元素,但是在Angular4中renderer
已经废弃掉了,变成了renderer2
。
renderer2
API中还有其他的一些方法可以用来进行一些DOM操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Renderer2 { data : {[key: string]: any} destroy() : void createElement(name: string, namespace?: string) : any createComment(value: string) : any createText(value: string) : any destroyNode : (node: any) => void | appendChild(parent: any, newChild: any) : void insertBefore(parent: any, newChild: any, refChild: any) : void removeChild(parent: any, oldChild: any) : void selectRootElement(selectorOrNode: string|any) : any parentNode(node: any) : any nextSibling(node: any) : any setAttribute(el: any, name: string, value: string, namespace?: string) : void removeAttribute(el: any, name: string, namespace?: string) : void addClass(el: any, name: string) : void removeClass(el: any, name: string) : void setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2) : void removeStyle(el: any, style: string, flags?: RendererStyleFlags2) : void setProperty(el: any, name: string, value: any) : void setValue(node: any, value: string) : void listen(target: 'window'|'document'|'body'|any, eventName: string, callback: (event: any) => boolean | void) : () => void }
|
参考文章
- [译]Angular2新人常犯的5个错误;
- Angular 2 ElementRef
- Angular Renderer2