Angular Directive Lifecycle

前端之家收集整理的这篇文章主要介绍了Angular Directive Lifecycle前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在介绍 Angular Directive Lifecycle (生命周期) 之前,我们先来介绍一下 Angular 中 Directive (指令) 与 Component (组件) 的关系。

我们再来看一下 Angular 中定义的指令和组件接口:

// angular2/packages/core/src/Metadata/directives.ts

export interface Directive {
   selector?: string;  // 用于定义组件在HTML代码中匹配的标签
   inputs?: string[];  // 指令的输入属性
   outputs?: string[];  // 指令的输出属性
   host?: {[key: string]: string};  // 绑定宿主的属性、事件等
   providers?: Provider[];  // 设置指令及其子指令可以用的服务
   exportAs?: string;  // 导出指令,使得可以在模板中调用
   queries?: {[key: string]: any};  // 设置指令的查询条件
}

export interface Component extends Directive {
   changeDetection?: ChangeDetectionStrategy;  // 指定组件使用的变化检测策略
   viewProviders?: Provider[];     // 设置组件及其子组件(不含ContentChildren)可以用的服务
   moduleId?: string;  // 包含该组件模块的 id,它被用于解析 模版和样式的相对路径
   templateUrl?: string;  // 为组件指定一个外部模板的URL地址
   template?: string;  // 为组件指定一个内联的模板
   styleUrls?: string[];  // 为组件指定一系列用于该组件的样式表文件
   styles?: string[];  // 为组件指定内联样式
   animations?: any[];  // 设置组件相关动画
   encapsulation?: ViewEncapsulation;  // 设置组件视图包装选项
   interpolation?: [string,string];  // 设置默认的插值运算符,默认是"{{"和"}}"
   entryComponents?: Array<Type<any>|any[]>;  // 设置需要被提前编译的组件
}

通过观察上图与 Angular 中指令与组件的接口定义,我们可以总结出指令与组件之间的关系:组件继承于指令,并扩展了与 UI 视图相关的属性,如 template、styles、animations、encapsulation 等。

下面我们进入正题,开始介绍 Angular 指令的生命周期,它是用来记录指令从创建、应用及销毁的过程。Angular 提供了一系列与指令生命周期相关的钩子,便于我们监控指令生命周期的变化,并执行相关的操作。Angular 中所有的钩子如下图所示:

怎么那么多钩子,是不是被吓到了,没事我们基于指令与组件的区别来分个类:

  • 指令与组件共有的钩子

    • ngOnChanges

    • ngOnInit

    • ngDoCheck

    • ngOnDestroy

  • 组件特有的钩子

    • ngAfterContentInit

    • ngAfterContentChecked

    • ngAfterViewInit

    • ngAfterViewChecked

生命周期的顺序

ngOnChanges()

当被绑定的输入属性的值发生变化时调用,该方法接受当前和上一属性值的SimpleChanges对象,首次调用一定会发生在ngOnInit()之前。

son.component.ts

export class SonComponent implements OnChanges {
  @Input()
  receive;
  sonText = 22222;
  ngOnChanges(changes: SimpleChanges) {
    console.log(111);
    console.log(changes.receive.prevIoUsValue);
  }
}

app.component.ts

export class AppComponent implements OnInit {
  father = 2222;
  ngOnInit() {
    setInterval(() => {
      this.father = Math.random() * 1000;
    },1000);
  }
}

html

<app-son [receive] = "father"></app-son>

<input type="text" [(ngModel)] = "receive">
<input type="text" [(ngModel)] = "sonText">

ngOnChanges()方法获取了一个对象,它把每个发生变化的属性名都映射到了一个SimpleChange对象, 该对象中有属性的当前值和前一个值。

Angular只会在输入属性的值变化时调用这个钩子。 而sonText不是输入属性,Angular不会关注这个属性的变化。

ngOnInit()

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

使用ngOnInit()有两个原因:

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

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

不要在组件的构造函数获取数据,一般用于依赖注入或执行简单的数据初始化操作。

ngOnInit()是组件获取初始数据的好地方。

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

我们访问这些属性的第一次机会,实际上是ngOnChanges()方法,Angular会在ngOnInit()之前调用它。 但是在那之后,Angular还会调用ngOnChanges()很多次。而ngOnInit()只会被调用一次。

你可以信任Angular会在创建组件后立刻调用ngOnInit()方法。 这里是放置复杂初始化逻辑的好地方。

ngDoCheck()

用这个方法来检测那些被Angular忽略的更改。在每个Angular变更检测周期中调用,ngOnChanges()和ngOnInit()之后。

son.component.ts

export class SonComponent implements DoCheck{
  @Input()
  receive;
  sonText = 22222;
  ngDoCheck() {
    console.log(1);
  }
}

虽然ngDoCheck()钩子可以监测到属性值什么时候发生了变化。但我们必须小心。 这个ngDoCheck钩子被非常频繁的调用,在每次变更检测周期之后,发生了变化的每个地方都会调它。

ngAfterContentInit()

当把内容投影进组件之后调用。第一次ngDoCheck()之后调用,只调用一次。只适用于组件。

ngAfterContentChecked()

每次完成被投影组件内容的变更检测之后调用。ngAfterContentInit()和每次ngDoCheck()之后调用。只适合组件。

ngAfterViewInit()

初始化完组件视图及其子视图之后调用。第一次ngAfterContentChecked()之后调用,只调用一次。只适合组件。

ngAfterViewChecked()

每次做完组件视图和子视图的变更检测之后调用。ngAfterViewInit()和每次ngAfterContentChecked()之后调用。只适合组件。

ngOnDestroy

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

猜你在找的Angularjs相关文章