Angular组件——组件生命周期(一)
组件声明周期以及angular的变化发现机制
红色方法只执行一次。
变更检测执行的绿色方法和和组件初始化阶段执行的绿色方法是一个方法。
总共9个方法。
每个钩子都是@angular/core库里定义的接口。
import { Component, OnInit } from '@angular/core'; @Component({
selector: 'app-life',
templateUrl: './life.component.html',
styleUrls: ['./life.component.css']
})
export class LifeComponent implements OnInit { constructor() { } ngOnInit() {
} }
虽然接口不是必须的,Angular检测到钩子方法就会去执行它,还是建议把接口写上。
一、钩子的调用顺序
import { Component, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, Input, SimpleChange, SimpleChanges } from '@angular/core'; let logIndex: number = 1; //计数器 @Component({
selector: 'app-life',
templateUrl: './life.component.html',
styleUrls: ['./life.component.css']
})
export class LifeComponent implements OnInit, OnChanges, DoCheck, AfterContentInit
, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
@Input()
name: string; logIt(msg: string) {
console.log(`# ${logIndex++} ${msg}`);
}
constructor() {
this.logIt("name属性在constructor里的值是: " + this.name);
} ngOnInit() {
this.logIt("name属性在OnInit里的值是: " + this.name);
} ngOnChanges(changes: SimpleChanges): void { // 传入一个SimpleChanges对象
let name = changes['name'].currentValue;
this.logIt("name属性在ngOnChanges里的值是: " + this.name);
} ngDoCheck(): void {
this.logIt("DoCheck");
} ngAfterContentInit() {
this.logIt("ngAfterContentInit");
} ngAfterContentChecked() {
this.logIt("ngAfterContentChecked");
} ngAfterViewInit() {
this.logIt("ngAfterViewInit");
} ngAfterViewChecked() {
this.logIt("ngAfterViewChecked");
}
ngOnDestroy() {
this.logIt("ngOnDestory");
}
}
初始化逻辑依赖输入属性的值时,初始化逻辑一定要写在ngOnInit里,不能写在constructor里面。
DoCheck在Angular的每个变更检测周期中调用。
ngAfterContentInit和ngAfterContentChecked跟模版,组件的内容投影相关的。
ngAfterViewInit和ngAfterViewChecked跟组件的模版,初始化视图相关的。
二、onChanges钩子
父组件初始化或修改子组件的输入参数时会被调用。
需要先理解js中可变对象 和 不可变对象。
//字符串是不可变的
var greeting = "Hello";
greeting = "Hello World";
//对象是可变的
var user = { name: "Tom" };
user.name = "Jerry";
例子:
child组件有3个属性,其中2个是输入属性。
父组件有一个greeting属性和一个name属性是Tom的user对象。
父组件要改变输入属性,所以greeting和user.name是双向绑定。
<div class="parent">
<h2>我是父组件</h2>
<div>问候语:<input type="text" [(ngModel)]="greeting"></div>
<div>
姓名:
<input type="text" [(ngModel)]="user.name">
</div>
<app-child [greeting]="greeting" [(user)]="user"> </app-child>
</div>
父组件改变两个input的值,值变化时候传入子组件的值也会变化,传入子组件的输入属性的值变化时会触发ngOnChanges()。
父组件初始化子组件。初始化的时候调一次ngOnChanges(),初始化后子组件的greeting变成Hello,也就是父组件上的greeting的值。
user变成一个name属性为Tom的对象。
改变输入属性的值,父组件问候语greeting改为Helloa。
Angular的变更检测刷新不可变对象,也就是greeting的值,然后调用ngOnChanges()方法,greeting的值从之前的hello,变为了Helloa。
修改user.name为Tomb,控制台上没有打印新的消息。
因为用户只是改变了可变对象user的属性,user对象的引用自身是没有改变的,所以onChanges()方法没有被调用。
虽然可变对象的属性改变不会触发ngOnChanges()方法调用,但是子组件的user对象的属性仍然改变了,由于Angular的变更监测机制仍然捕获了组件中每个对象的属性变化。
改变子组件的message属性也不引起子组件的onChanges()方法调用。因为message不是输入属性。而ngOnChanges()只有在输入属性变化时候被调用。
三、变更检测机制和DoCheck()钩子
变更检测由zone.js实现的。保证组件的属性变化和页面的变化同步。浏览器中发生的异步事件(点击按钮,输入数据,数据从服务器返回,调用了setTimeout()方法)都会触发变更检测。
变更检测运行时,检测组件模版上的所有绑定关系,如果组件属性被改变,与其绑定的模版相应区域可能需要更新。
注意:变更检测机制只是将组件属性的改变反应到模版上,变更检测机制本身永远不会改变组件属性的值。
两种变更检测策略。
- Default 检测到变化,检查整个组件树。
- OnPush 只有当输入属性变化时,才去检测该组件及其子组件。
Angular应用是一个以主组件为根的组件树,每个组件都会生成一个变更检测器,任何一个变更检测器检测到变化,zone.js就根据组件的变更检查策略来检测组件(也就是调doCheck()钩子),来判断组件是否需要更新它的模版。
DoCheck检查是从根组件开始往下检查所有的组件树,不管变更发生在哪个组件。
例子:
监控user.name这种可变对象的属性的改变。
在child中加一个oldUsername来存变更前的username,加一个changeDetected属性标志username是否发生变化,默认是false。 noChangeCount计数器默认是0。
import { Component, OnInit, Input, OnChanges, SimpleChanges, DoCheck } from '@angular/core'; @Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck { @Input()
greeting: string; @Input()
user: { name: string }; message: string = "初始化消息";
oldUsername: string;
changeDetected: boolean = false;
noChangeCount: number = 0; constructor() { } ngOnInit() {
} ngOnChanges(changes: SimpleChanges): void {
console.log(JSON.stringify(changes, null, 2));
} ngDoCheck() {
if (this.user.name !== this.oldUsername) {
this.changeDetected = true;
console.log("DoCheck: user.name 从 " + this.oldUsername + "变为" + this.user.name);
this.oldUsername = this.user.name;
}
if (this.changeDetected) {//变化来计数器清0
this.noChangeCount = 0;
} else {//没变化
this.noChangeCount++;
console.log("DoCheck:user.name没变化时ngDoCheck方法已经被调用" + this.noChangeCount + "次")
}
this.changeDetected = false;//最后不管变没变标志位复位
} }
页面加载完成:user.name没变化时DoCheck方法已经被调用1次。
鼠标点击,不改变任何值,点击触发变更检测机制,所有组件的DoCheck就会被调用。
修改Tom为Tomb,DoCheck捕捉到Tom变为Tomb。
虽然DoCheck()钩子可以检测到user.name什么时候发生变化,但是使用必须小心,ngDoCheck()钩子被非常频繁的调用。每次变更检测周期后发生变化的地方都会调用。
对ngDoCheck()的实现必须非常高效,非常轻量级,否则容易引起性能问题。
同理:所有带Check关键字的钩子方法都要非常小心。 ngDoCheck,ngAfterContentChecked,ngAfterViewChecked.
本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/8641491.html 有问题欢迎与我讨论,共同进步。
Angular组件——组件生命周期(一)的更多相关文章
- Angular 4 组件的生命周期
1.组件的生命周期
- ReactJS入门(二)—— 组件的生命周期
如果你熟悉avalon,使用过 data-include-rendered 和 data-include-loaded 等回调方法,那么你会很好地理解React组件的各个生命周期. 说白了其实就是Re ...
- React Native 中组件的生命周期
概述 就像 Android 开发中的 View 一样,React Native(RN) 中的组件也有生命周期(Lifecycle).所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命 ...
- 《微信小程序七日谈》- 第三天:玩转Page组件的生命周期
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 前两篇 ...
- reactjs入门到实战(七)---- React的组件的生命周期
React的组件的生命周期有三个状态分别是:挂载(生产组件示例化.准备挂载到页面.挂载到页面).更新(更新值.更新DOM).和卸载(卸载后). >>>其他 getInitia ...
- react.js 从零开始(二)组件的生命周期
什么是生命周期? 组件本质上是一个状态机,输入确定,输出一定确定. 当状态改变的时候 会触发不同的钩子函数,可以让开发者做出响应.. 一个组件的生命周期可以概括为 初始化:状态下 可以自定义的函数 g ...
- Flex组件的生命周期
组件实例化生命周期描述了用组件类创建组件对象时所发生的一系列步骤,作为生命周期的一部分,flex自动调用组件的的方法,发出事件,并使组件可见. 下面例子用as创建一个btn控件,并将其加入容器中 va ...
- react 组件的生命周期
组件的生命周期 过程 装载(Mounting) :组件被插入到 DOM 中: 更新(Updating) :组件重新渲染以更新 DOM: 卸载(Unmounting) :组件从 DOM 中移除. 过程 ...
- ReactJS入门3:组件的生命周期
本文主要介绍组件的生命周期. 组建的生命周期主要分为3个:Mounting.Updating.Unmounting. 1. Mounting:组件被加载到DOM 在本阶段,主要有三个方法: 1 ...
- vue的组件和生命周期
Vue里组件的通信 通信:传参.控制.数据共享(A操控B做一个事件) 模式:父子组件间.非父子组件 父组件可以将一条数据传递给子组件,这条数据可以是动态的,父组件的数据更改的时候,子组件接收的也会变化 ...
随机推荐
- 【CJOJ1494】【洛谷2756】飞行员配对方案问题
题面 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1 ...
- Bzoj4555: [Tjoi2016&Heoi2016]求和
题面 Bzoj Sol 推柿子 因为当\(j>i\)时\(S(i, j)=0\),所以有 \[\sum_{i=0}^{n}\sum_{j=0}^{n}S(i, j)2^j(j!)\] 枚举\(j ...
- Spring9:Autowire(自动装配)机制
为什么Spring要支持Autowire(自动装配) 先写几个类,首先定义一个Animal接口表示动物: public interface Animal { public void eat(); } ...
- oracle 裸设备划分 --centos6.5
主题思想:物理卷PV->卷组VG->逻辑卷LV(类型:raw)->添加表空间 操作过程 vg_orcl 8g 一:划分 二:创建裸设备 方法1:目前最常用的方法 #c ...
- react ( 二 )
ref属性 当我们在 react组件中要访问真实的DOM元素时,你可能需要用到ref属性,ref接收一个函数作为属性值,函数接收一个参数,这个参数就是真实的DOM元素.真实的DOM元素渲染到页面上之后 ...
- Lintcode249 Count of Smaller Number before itself solution 题解
[题目描述] Give you an integer array (index from 0 to n-1, where n is the size of this array, data value ...
- Google Maps API的使用
之前在学习了简单的API调用后,查看了几个知名网站的API调用方法,发现Google的API调用还是相对比较简单的.下面就从API key的获取.googlemaps的安装,再到实际使用做一下说明. ...
- BZOJ4825 单旋
分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap. 画一画图就可以解决这道题了,自己试一下. 代码如下: #include<bits/stdc++.h&g ...
- The method queryForMap(String, Object...) from the type JdbcTemplate refers to the missing type DataAccessException
Add spring-tx jar of your spring version to your classpath.
- 2018世界气象日,API为气象助力
"世界气象日"(World Meteorological Day)又称"国际气象日",是[世界气象组织]成立的纪念日. 国际气象组织的前身原为非官方性国际气象合 ...