angular学习之路5-生命周期钩子

1,

指令和组件的实例有一个生命周期:当 Angular 新建、更新和销毁它们时触发。 通过实现一个或多个 Angular core 库里定义的生命周期钩子接口,开发者可以介入该生命周期中的这些关键时刻。

每个接口都有唯一的一个钩子方法,它们的名字是由接口名再加上 ng 前缀构成的。比如,OnInit 接口的钩子方法叫做 ngOnInit, Angular 在创建组件后立刻调用它,:

生命周期的顺序

当 Angular 使用构造函数新建一个组件或指令后,就会按下面的顺序在特定时刻调用这些生命周期钩子方法:

钩子

用途及时机

ngOnChanges()

当 Angular(重新)设置数据绑定输入属性时响应。 该方法接受当前和上一属性值的 SimpleChanges 对象

在 ngOnInit() 之前以及所绑定的一个或多个输入属性的值发生变化时都会调用。

ngOnInit()

在 Angular 第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。

在第一轮 ngOnChanges() 完成之后调用,只调用一次

ngDoCheck()

检测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应。

在每个变更检测周期中,紧跟在 ngOnChanges() 和 ngOnInit() 后面调用。

ngAfterContentInit()

当 Angular 把外部内容投影进组件/指令的视图之后调用。

第一次 ngDoCheck() 之后调用,只调用一次。

ngAfterContentChecked()

每当 Angular 完成被投影组件内容的变更检测之后调用。

ngAfterContentInit() 和每次 ngDoCheck() 之后调用

ngAfterViewInit()

当 Angular 初始化完组件视图及其子视图之后调用。

第一次 ngAfterContentChecked() 之后调用,只调用一次。

ngAfterViewChecked()

每当 Angular 做完组件视图和子视图的变更检测之后调用。

ngAfterViewInit() 和每次 ngAfterContentChecked() 之后调用。

ngOnDestroy()

每当 Angular 每次销毁指令/组件之前调用并清扫。 在这儿反订阅可观察对象和分离事件处理器,以防内存泄漏。

在 Angular 销毁指令/组件之前调用。

//探测指令

// Spy on any element to which it is applied.
// Usage: <div mySpy>...</div>
@Directive({selector: '[mySpy]'})
export class SpyDirective implements OnInit, OnDestroy {

  constructor(private logger: LoggerService) { }

  ngOnInit()    { this.logIt(`onInit`); }

  ngOnDestroy() { this.logIt(`onDestroy`); }

  private logIt(msg: string) {
    this.logger.log(`Spy #${nextId++} ${msg}`);
  }
}

你可以把这个侦探指令写到任何原生元素或组件元素上,它将与所在的组件同时初始化和销毁。 下面是把它附加到用来重复显示英雄数据的这个 <div> 上。

<div *ngFor="let hero of heroes" mySpy class="heroes">
  {{hero}}
</div>

OnInit()

使用 ngOnInit() 有两个原因:

  1. 在构造函数之后马上执行复杂的初始化逻辑

  2. 在 Angular 设置完输入属性之后,对该组件进行准备。

不要在组件的构造函数中获取数据? 在测试环境下新建组件时或在你决定要显示它之前,不应该担心它会尝试联系远程服务器。 构造函数中除了使用简单的值对局部变量进行初始化之外,什么都不应该做。

另外还要记住,在指令的构造函数完成之前,那些被绑定的输入属性还都没有值。 如果你需要基于这些属性的值来初始化这个指令,这种情况就会出问题。 而当 ngOnInit() 执行的时候,这些属性都已经被正确的赋值过了。

ngOnChanges() 方法是你访问这些属性的第一次机会。Angular 会在 ngOnInit() 之前调用 ngOnChanges(),之后还会调用很多次。但只会调用一次 ngOnInit()

OnChanges()

一旦检测到该组件(或指令)的输入属性发生了变化,Angular 就会调用它的 ngOnChanges() 方法。 本例监控 OnChanges 钩子。

ngOnChanges(changes: SimpleChanges) {
  for (let propName in changes) {
    let chng = changes[propName];
    let cur  = JSON.stringify(chng.currentValue);
    let prev = JSON.stringify(chng.previousValue);
    this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
  }
}

DoCheck()

使用 DoCheck 钩子来检测那些 Angular 自身无法捕获的变更并采取行动

用这个方法来检测那些被 Angular 忽略的更改。

虽然 ngDoCheck() 钩子可以可以监测到英雄的 name 什么时候发生了变化。但其开销很恐怖。 这个 ngDoCheck 钩子被非常频繁的调用 —— 在每次变更检测周期之后,发生了变化的每个地方都会调它。 在这个例子中,用户还没有做任何操作之前,它就被调用了超过二十次。

AfterView

AfterView 例子展示了 AfterViewInit() 和 AfterViewChecked() 钩子,Angular 会在每次创建了组件的子视图后调用它们。

下面是一个子视图,它用来把英雄的名字显示在一个 <input> 中:

@Component({
  selector: 'app-child-view',
  template: '<input [(ngModel)]="hero">'
})
export class ChildViewComponent {
  hero = 'Magneta';
}

注意,Angular 会频繁的调用 AfterViewChecked(),甚至在并没有需要关注的更改时也会触发。 所以务必把这个钩子方法写得尽可能精简,以免出现性能问题。

AfterContent

AfterContent 例子展示了 AfterContentInit() 和 AfterContentChecked() 钩子,Angular 会在外来内容被投影到组件中之后调用它们。

内容投影

内容投影是从组件外部导入 HTML 内容,并把它插入在组件模板中指定位置上的一种途径。

下列迹象表明存在着内容投影

  • 在组件的元素标签中有 HTML

  • 组件的模板中出现了 <ng-content> 标签

AfterContent 钩子

AfterContent 钩子和 AfterView 相似。关键的不同点是子组件的类型不同。

  • AfterView 钩子所关心的是 ViewChildren,这些子组件的元素标签会出现在该组件的模板里面

  • AfterContent 钩子所关心的是 ContentChildren,这些子组件被 Angular 投影进该组件中。

使用 AfterContent 时,无需担心单向数据流规则

该组件的 doSomething() 方法立即更新了组件被绑定的 comment 属性。 它不用等下一回合。

回忆一下,Angular 在每次调用 AfterView 钩子之前也会同时调用 AfterContent。 Angular 在完成当前组件的视图合成之前,就已经完成了被投影内容的合成。 所以你仍然有机会去修改那个视图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值