详解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.

以上就是详解Angular组件生命周期(一)的详细内容,更多关于Angular组件生命周期的资料请关注我们其它相关文章!

(0)

相关推荐

  • AngularJS深入探讨scope,继承结构,事件系统和生命周期

    本文实例讲述了AngularJS的scope,继承结构,事件系统和生命周期.分享给大家供大家参考,具体如下: 深入探讨 Scope 作用域 每一个 $scope 都是类 Scope 的一个实例.类 Scope 拥有可以控制 scope 生命周期的方法,提供事件传播的能力,并支持模板渲染. 作用域的层次结构 让我们再来看看这个简单的 HelloCtrl 的例子: var HelloCtrl = function($scope){ $scope.name = 'World'; } HelloCtrl

  • 浅谈对Angular中的生命周期钩子的理解

    本文介绍了Angular中的生命周期钩子的理解,分享给大家,希望对大家有所帮助 什么是生命周期钩子 简单点来说生命周期钩子就是Angular中一个组件从被创建当销毁期间的一些有意义的关键时刻.这些关键时刻在Angular中被Angular核心模块 @angular/core 暴露出来,赋予了我们在它们发生时采取行动的能力. 有哪些生命周期钩子 Angular中从一个组件的创建到销毁一个有八个生命周期钩子它们,按照先后顺序.它们分别是: ngOnChanges() ngOnInit() ngDoC

  • 浅谈angular2 组件的生命周期钩子

    本文介绍了浅谈angular2 组件的生命周期钩子,分享给大家,具体如下: 按照生命周期执行的先后顺序,Angular生命周期接口如下所示 名称 时机 接口 范围 ngOnChanges 当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在 ngOnInit之前. OnChanges 指令和组件 ngOnInit 在第一轮 ngOnChanges 完成之后调用. ( 译注:也就是说当每个输入属性的值都被触发了一次 ngOnChanges之后才会调用 ngOnInit ,此时所有输入属性都已

  • 浅析AngularJS中的生命周期和延迟处理

    这里,我们再讨论一些常用的高级的控制反转容器(Inversion of Control containers):延迟加载(lazy-loading),生命周期管理(lifetime management),以及延迟的创建/处理(deferred creation/resolution).   延迟加载(Lazy-Loading) 所谓延迟加载就是当你需要用到对象时候才对其进行实例化.许多依赖注入系统都会在一开始就创建组件,作为它的可依赖项目.不过有时候,直到在应用中用到它们之前,你都不会想去实例

  • 浅谈angular4生命周期钩子

    理解 Angular提供了生命周期钩子,把这些关键生命时刻暴露出来,赋予我们在它们发生时采取行动的能力.可以将钩子函数理解为在合适的时候做合适的事情. 钩子函数 ng4主要提供了8个钩子函数: 1.ngOnchanges @input属性(输入属性)发生变化时,会调用.非此属性,不会调用. 当输入属性为对象时,当对象的属性值发生变化时,不会调用,当对象的引用变化时会触发. 先于ngOnInit调用. 2.ngOnInit 只执行一次,dom操作可放在其中.(最常用) 3.NgDocheck 每次

  • 深入解析AngularJS框架中$scope的作用与生命周期

    $scope 的使用贯穿整个 Angular App 应用,它与数据模型相关联,同时也是表达式执行的上下文.有了 $scope 就在视图和控制器之间建立了一个通道,基于作用域视图在修改数据时会立刻更新 $scope,同样的 $scope 发生改变时也会立刻重新渲染视图. 有了 $scope 这样一个桥梁,应用的业务代码可以都在 controller 中,而数据都存放在controller 的 $scope 中. $scope是一个把view(一个DOM元素)连结到controller上的对象.在

  • Angular2生命周期钩子函数的详细介绍

    Angular每个组件都存在一个生命周期,从创建,变更到销毁.Angular提供组件生命周期钩子,把这些关键时刻暴露出来,赋予在这些关键结点和组件进行交互的能力,掌握生命周期,可以让我们更好的开发Angular应用 概述 每个接口都有唯一的一个钩子方法,它们的名字是由接口名再加上ng前缀构成的.比如,OnInit接口的钩子方法叫做ngOnInit, Angular在创建组件后立刻调用它 生命周期执行顺序 ngOnChanges 在有输入属性的情况下才会调用,该方法接受当前和上一属性值的Simpl

  • 详解Angular组件生命周期(一)

    概述 组件声明周期以及angular的变化发现机制 红色方法只执行一次. 变更检测执行的绿色方法和和组件初始化阶段执行的绿色方法是一个方法. 总共9个方法. 每个钩子都是@angular/core库里定义的接口. import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-life', templateUrl: './life.component.html', styleUrls: ['./life

  • 详解Angular组件之生命周期(二)

    一.view钩子 view钩子有2个,ngAfterViewInit和ngAfterViewChecked钩子. 1.实现ngAfterViewInit和ngAfterViewChecked钩子时注意事项 以父组件调用子组件方法中例子为基础,在父组件中实现ngAfterViewInit和ngAfterViewChecked钩子. 这两个钩子是在组件的模版所有内容组装完成后,组件模版已经呈现给用户看了,之后这两个钩子方法会被调用. @ViewChild('child1') child1:Child

  • 详解Angular组件之投影

    概述 运行时动态改变组件模版的内容.没路由那么复杂,只是一段html,没有业务逻辑. ngContent指令将父组件模版上的任意片段投影到子组件上. 一.简单例子 1.子组件中使用<ng-content>指令来标记投影点 <div class="wrapper"> <h2>我是子组件</h2> <div>这个div定义在子组件中</div> <ng-content></ng-content>

  • 详解Angular组件之中间人模式

    一.中间人模式 该组件树中除了组件1以外,每个组件都有一个父组件可以扮演中间人的角色.顶级的中间人是组件1,它可以使组件2,组件3,组件6之间互相通讯.依次类推,组件2是组件4和组件5的中间人.组件3是组件7和组件8的中间人. 中间人负责从一个组件接收数据并将其传递给另一个组件. 二.例子 股票报价组件为例,假设交易员在监看着报价组件的价格,当股票价格达到某一个值的时候,交易员会点一个购买按钮,来购买股票.问题:报价组件并不知道应该如何下单来买股票,它只是用来监控股票价格的.所以报价组件在这时应

  • 详解Angular组件数据不能实时更新到视图上的问题

    目录 问题起源 OnPush策略 当前组件或子组件之一触发了事件 总结 问题起源 MainComponent: @Component({ selector: 'main', template: ` <MenuComponent [isReport]="isReport"> </MenuComponent> `, changeDetection:ChangeDetectionStrategy.OnPush }) export class MainComponent

  • 全面详解Spring Bean生命周期教程示例

    目录 Spring 中 Bean 的生命周期 Bean 的实例化 构造方法注入 工厂方法注入 Bean 的属性赋值 setter注入 构造方法注入 Bean 的初始化 初始化方法 InitializingBean 接口 Bean 的销毁 销毁方法 DisposableBean 接口 总结 Spring 中 Bean 的生命周期 是当今最流行的 Java 开发框架之一,其强大的 Bean容器机制是其中的核心之一.Bean 是指在 Spring 容器中被管理的对象,它们可以被注入到其他对象中,也可以

  • vue组件生命周期钩子使用示例详解

    目录 组件生命周期图 组件生命周期钩子 1.beforeCreate 2.created 3.beforeMount 4.mounted 5.beforeUpdate 6.updated 7.activated 8.deactivated 9.beforeDestroy 10.destroyed 11.errorCaptured 组件生命周期图 组件生命周期钩子 所有的生命周期钩子自动绑定 一.组件的生命周期:一个组件从创建到销毁的整个过程 二.生命周期钩子:在一个组件生命周期中,会有很多特殊的

  • vue组件生命周期详解

    本文实例为大家分享了vue组件生命周期的具体代码,供大家参考,具体内容如下 分为4个阶段: create/mount/update/destroy 每一个阶段都对应着有自己的处理函数 create: beforeCreate created 初始化 mount: beforeMount mounted 和挂载相关的处理 update: beforeUpdate updated 根据要更新的数据 做逻辑判断 destroy:beforeDestroy destroyed 清理工作 代码: <!do

  • React组件生命周期详解

    调用流程可以参看上图. React组件提供了生命周期的钩子函数去响应组件不同时刻的状态,组件的生命周期如下: 实例化 存在期 销毁期 实例化 首次调用组件时,有以下方法会被调用(注意顺序,从上到下先后执行): getDefaultProps 这个方法是用来设置组件默认的props,组件生命周期只会调用一次.但是只适合react.createClass直接创建的组件,使用ES6/ES7创建的这个方法不可使用,ES6/ES7可以使用下面方式: //es7 class Component { stat

  • 详解Angular父子组件通讯

    概述 Angular组件间通讯 组件树,1号是根组件AppComponent. 组件之间松耦合,组件之间知道的越少越好. 组件4里面点击按钮,触发组件5的初始化逻辑. 传统做法:在按钮4的点击事件里调用组件5的方法.紧密耦合. Angular:在组件4根本不知道组件5存在的情况下实现. 使用松耦合的方式在组件之间传递数据开发出高重用性的组件. 使用输入输出属性在父子关系的组件之间传递数据. 一.输入输出属性概述 组件设计成黑盒模型,用输入属性声明从外部世界接收什么东西.不需要知道这些东西从哪里来

随机推荐