constructor和ngOnInit钩子有什么不同?
constructor
constructor(构造函数)是ES6类或TypeScript类中的特殊方法,而不是Angular的方法,主要用来做初始化操作,在进行类实例化操作是,会被自动调用。通过constructor方法并不能使我们知道Angular何时完成了组件的初始化工作。
仅显示constructor方法:
import { Component } from ' @angular/core ' ;
@Component({})
class ExampleComponent {
// this is called by the JavaScript engine
// rather than Angular
constructor(name) {
console.log( ' Constructor initialised ' );
this .name = name;
}
}
// internally calls the constructor
let appCmp = new ExampleComponent( ' AppCmp ' );
console.log(appCmp.name);
运行以上代码,控制台输出结果:
Constructor initialization AppCmp
constructor方法是由JavaScript引擎调用的,而不是Angular,这就是为什么ngOnInit生命周期钩子被创建的原因。
ngOnInit
ngOnInit 是 Angular 2 组件生命周期中的一个钩子,Angular 2 中的所有钩子和调用顺序如下:
ngOnChanges - 当数据绑定输入属性的值发生变化时调用
ngOnInit - 在第一次 ngOnChanges 后调用
ngDoCheck - 自定义的方法,用于检测和处理值的改变
ngAfterContentInit - 在组件内容初始化之后调用
ngAfterContentChecked - 组件每次检查内容时调用
ngAfterViewInit - 组件相应的视图初始化之后调用
ngAfterViewChecked - 组件每次检查视图时调用
ngOnDestroy - 指令销毁前调用
其中 ngOnInit 用于在 Angular 获取输入属性后初始化组件,该钩子方法会在第一次 ngOnChanges 之后被调用。
另外需要注意的是 ngOnInit 钩子只会被调用一次,我们来看一下具体示例:
import { Component, OnInit } from ' @angular/core ' ;
@Component({
selector: ' my-app ' ,
template: `
<h1>Welcome to Angular World</h1>
<p>Hello {{name}}</p>
`,
})
export class AppComponent implements OnInit {
name: string = '' ;
constructor() {
console.log( ' Constructor initialization ' );
this .name = ' Semlinker ' ;
}
ngOnInit() {
console.log( ' ngOnInit hook has been called ' );
}
}
?
以上代码运行后,控制台输出结果:
Constructor initialization ngOnInit hook has been called
接下来看一个父-子组件传参的例子:
parent测试数据ponent.ts
import { Component } from ' @angular/core ' ;
@Component({
selector: ' exe-parent ' ,
template: `
<h1>Welcome to Angular World</h1>
<p>Hello {{name}}</p>
<exe-child [pname]= " name " ></exe-child>
`,
})
export class ParentComponent {
name: string = '' ;
constructor() {
this .name = ' Semlinker ' ;
}
}
child测试数据ponent.ts
import { Component, Input, OnInit } from ' @angular/core ' ;
@Component({
selector: ' exe-child ' ,
template: `
<p>父组件的名称:{{pname}} </p>
`
})
export class ChildComponent implements OnInit {
@Input()
pname: string ; // 父组件的名称
constructor() {
console.log( ' ChildComponent constructor ' , this .pname); // Output:undefined
}
ngOnInit() {
console.log( ' ChildComponent ngOnInit ' , this .pname);
}
}
以上代码运行后,控制台输出结果:
ChildComponent constructor undefined ChildComponent ngOnInit Semlinker
我们发现在 ChildComponent 构造函数中,是无法获取输入属性的值,而在 ngOnInit 方法中,我们能正常获取输入属性的值。因为 ChildComponent 组件的构造函数会优先执行,当 ChildComponent 组件输入属性变化时会自动触发 ngOnChanges 钩子,然后在调用 ngOnInit 钩子方法,所以在 ngOnInit 方法内能获取到输入的属性。
constructor 应用场景
在 Angular 2 中,构造函数一般用于依赖注入或执行一些简单的初始化操作。
import { Component, ElementRef } from ' @angular/core ' ;
@Component({
selector: ' my-app ' ,
template: `
<h1>Welcome to Angular World</h1>
<p>Hello {{name}}</p>
`,
})
export class AppComponent {
name: string = '' ;
constructor( public elementRef: ElementRef) { // 使用构造注入的方式注入依赖对象
this .name = ' Semlinker ' ; // 执行初始化操作
}
}
ngOnInit 应用场景
在项目开发中我们要尽量保持构造函数简单明了,让它只执行简单的数据初始化操作,因此我们会把其他的初始化操作放在 ngOnInit 钩子中去执行。如在组件获取输入属性之后,需执行组件初始化操作等。
import { Component, OnInit } from ' @angular/core ' ;
@Component({})
class ExampleComponent implements OnInit {
constructor() {}
// called on demand by Angular
ngOnInit() {
console.log( ' ngOnInit fired ' );
}
}
const instance = new ExampleComponent();
// Angular calls this when necessary
instance.ngOnInit();
?
查看更多关于Angular2 constructor VS ngOnInit的详细内容...