Dom操作
1.Dom操作的两种方法
对于DOM操作,有两种方法可以实现,第一种是使用原生的js来获取dom节点,进而操作节点;第二种是使用ViewChild获取获取dom节点;下面具体来介绍这两种方法:
第一种:
对于一般的dom节点,使用原生js可以顺利拿到它的节点,像这样:
<div id="box1">this is box1</div>
ngOnInit(): void {
// 在ngOnInit函数中,只是组件和指令初始化完成,并不是真正的dom加载完成。
let box1=document.getElementById('box1');
console.log(box1?.innerText);
}
控制台:
但是对于带有angular特殊指令的节点,就不行了:
<div id="box1">this is box1</div>
<div id="box2" *ngIf="flag">this is box2</div>
export class DomComponent implements OnInit {
public flag:boolean=true;
constructor() { }
ngOnInit(): void {
// 在ngOnInit函数中,只是组件和指令初始化完成,并不是真正的dom加载完成。
let box1=document.getElementById('box1');
console.log(box1?.innerHTML);
let box2=document.getElementById('box2');
console.log(box2?.innerText);
}
}
我们可以在控制台看到没有输出box2的内容
这是因为在生命周期ngOnInit函数中,只是组件和指令初始化完成,并不是真正的dom加载完成,而因为angular指令的存在拿不到dom节点。为了解决这个问题,我们可以把获取dom节点的操作放在ngAfterViewInit函数内,如:
export class DomComponent implements OnInit {
public flag:boolean=true;
constructor() { }
ngOnInit(): void {
// 在ngOnInit函数中,只是组件和指令初始化完成,并不是真正的dom加载完成。
// let box1=document.getElementById('box1');
// console.log(box1?.innerHTML);
// let box2=document.getElementById('box2');
// console.log(box2?.innerText);
}
ngAfterViewInit():void{
let box1=document.getElementById('box1');
console.log(box1?.innerHTML);
let box2=document.getElementById('box2');
console.log(box2?.innerText);
}
}
第二种方法,使用ViewChild获取dom节点,步骤:
首先,用# 节点名 给要获取的节点命名,如:
<div #box3>this is box3</div>
然后使用@ViewChild()装饰器来获取dom节点,括号内的是上面的节点名,然后外边的是变量,意思是将获取的dom节点赋给这个变量,如:
@ViewChild('box3') box3:any;
最后,记得在ngAfterViewInit函数中操作dom:
export class DomComponent implements OnInit {
public flag:boolean=true;
//获取dom节点
@ViewChild('box3') box3:any;
constructor() { }
ngOnInit(): void {
// 在ngOnInit函数中,只是组件和指令初始化完成,并不是真正的dom加载完成。
// let box1=document.getElementById('box1');
// console.log(box1?.innerHTML);
// let box2=document.getElementById('box2');
// console.log(box2?.innerText);
}
ngAfterViewInit():void{
// let box1=document.getElementById('box1');
// console.log(box1?.innerHTML);
// let box2=document.getElementById('box2');
// console.log(box2?.innerText);
console.log(this.box3.nativeElement.innerText);
}
}
控制台:
利用ViewChild不仅可以获取dom节点,还能获取子组件,下面的例子是father组件使用son组件的get方法获取son里边的数据:
father组件:
<p>this is father!</p>
<app-son #son></app-son>
import { Component, OnInit,ViewChild } from '@angular/core';
@Component({
selector: 'app-father',
templateUrl: './father.component.html',
styleUrls: ['./father.component.css']
})
export class FatherComponent implements OnInit {
@ViewChild('son') son:any;
constructor() { }
ngOnInit(): void {
}
ngAfterViewInit():void{
this.son.get();
}
}
son组件:
<p>this is son!</p>
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-son',
templateUrl: './son.component.html',
styleUrls: ['./son.component.css']
})
export class SonComponent implements OnInit {
public num:number=1;
constructor() { }
get(){
console.log(this.num);
}
ngOnInit(): void {
}
}
控制台:
2.angular里面的生命周期函数
angular的每个组件都存在生命周期,从创建,变更到销毁。angular提供组件生命周期钩子,把这些关键时刻暴露出来。赋予在关键节点和组件进行交互的能力。
生命周期执行顺序
ngOnChanges
在有输入属性的时候才会调用,该方法接收一个类型为SimpleChanges的对象,如果有输入属性,会在ngOnInit之前调用。
SimpleChanges的值包含:previousValue:any,currentValue:any,firstChange:boolean
ngOnInit
组件初始化,只调用一次,在第一次调用ngOnChange时调用。
ngDoCheck
在组件定义的属性或方法变更时调用(用于脏值检查,非常消耗性能,因为会把所有的属性和方法都检查一遍),会在ngOnChange和ngOnInit之后调用。
ngAfterContentInit
在组件内容初始化之后调用,在第一次ngDoCheck之后调用,只调用一次。
ngAfterContentChecked
在组件每次检查内容发生变更时调用。在ngAfterContentInit和每次ngDoCheck之后调用。
ngAfterViewInit
在组件相应的视图初始化之后调用,第一次ngAfterContentCheck之后调用,只调用一次。
ngAfterViewChecked
在组件每次检查视图发生变更时调用,在ngAfterViewInit和每次ngAfterContentChecked之后调用。
ngOnDestroy
在组件销毁前调用,做一些清理工作,比如退订可观察对象(subscription)和移除事件处理器,以免导致内存泄漏。
constructor和ngOnInit
constructor是ES6中class中新增的属性,当class类实例化的时候调用constructor来初始化类。angular中的组件是基于class类实现的,在angular中,constructor用来依赖注入。
ngOnInit是angular生命周期的一部分,在constructor之后执行,在angular中用于初始化变量和数据绑定。
ngAfterContentInit和ngAfterViewInit的区别
view:是当前组件的模板。
content:通常指被映射到一个组件的ng-content中的内容。
视图初始化在内容之后,所以ngAfterViewInit在ngAfterContentInit之后执行。