Angular默认提供了生命周期钩子ngOnInit。
为什么要使用ngOnInit,如果我们已经有一个构造函数?
Angular默认提供了生命周期钩子ngOnInit。
为什么要使用ngOnInit,如果我们已经有一个构造函数?
当前回答
构造函数在类实例化时执行。它与棱角无关。这是Javascript的特性,Angular无法控制它
ngOnInit是Angular特有的,当Angular用所有输入属性初始化组件时,它会被调用
@Input属性在ngOnInit生命周期钩子下可用。这将帮助你做一些初始化的事情,比如从后端服务器获取数据等显示在视图中
@Input属性在构造函数中显示为未定义
其他回答
第一个(构造函数)与类实例化有关,与Angular2无关。构造函数可以用在任何类上。您可以在其中放入一些新创建实例的初始化处理。
第二个对应于Angular2组件的生命周期钩子:
引用自angular官方网站:
当输入或输出绑定值发生变化时调用ngOnChanges 在第一个ngOnChanges之后调用ngOnInit
所以如果初始化处理依赖于组件的绑定(例如用@Input定义的组件参数),你应该使用ngOnInit,否则构造函数就足够了…
我将添加一个重要的东西,在上面的解释中被跳过,并解释什么时候你必须使用ngOnInit。
如果你通过ViewChildren, ContentChildren或ElementRef对组件的DOM进行任何操作,你的原生元素在构造函数阶段将不可用。
然而,由于ngOnInit发生在组件被创建和检查(ngOnChanges)被调用之后,你可以在这一点上访问DOM。
export class App implements OnInit, AfterViewInit, AfterContentInit {
@Input() myInput: string;
@ViewChild() myTemplate: TemplateRef<any>;
@ContentChild(ChildComponent) myComponent: ChildComponent;
constructor(private elementRef: ElementRef) {
// this.elementRef.nativeElement is undefined here
// this.myInput is undefined here
// this.myTemplate is undefined here
// this.myComponent is undefine here
}
ngOnInit() {
// this.elementRef.nativeElement can be used from here on
// value of this.myInput is passed from parent scope
// this.myTemplate and this.myComponent are still undefined
}
ngAfterContentInit() {
// this.myComponent now gets projected in and can be accessed
// this.myTemplate is still undefined
}
ngAfterViewInit() {
// this.myTemplate can be used now as well
}
}
我认为最好的例子是使用服务。假设我想在我的组件“激活”时从我的服务器获取数据。假设我还想在从服务器获取数据后对数据做一些额外的处理,也许我得到了一个错误,想要以不同的方式记录它。
在构造函数上使用ngOnInit真的很容易,它还限制了我需要添加到应用程序中的回调层的数量。
例如:
export class Users implements OnInit{
user_list: Array<any>;
constructor(private _userService: UserService){
};
ngOnInit(){
this.getUsers();
};
getUsers(){
this._userService.getUsersFromService().subscribe(users => this.user_list = users);
};
}
对于构造函数,我可以只调用我的_userService并填充我的user_list,但也许我想对它做一些额外的事情。比如确保所有内容都是大写的,我不完全确定我的数据是如何通过的。
这让使用ngOnInit更容易。
export class Users implements OnInit{
user_list: Array<any>;
constructor(private _userService: UserService){
};
ngOnInit(){
this.getUsers();
};
getUsers(){
this._userService.getUsersFromService().subscribe(users => this.user_list = users);
this.user_list.toUpperCase();
};
}
它使它更容易看到,所以当我初始化时,我只是在组件中调用我的函数而不是在其他地方寻找它。实际上,它只是另一个工具,可以让你在将来更容易阅读和使用。此外,我发现将函数调用放在构造函数中是非常糟糕的实践!
为了测试这一点,我从NativeScript教程中借鉴编写了以下代码:
user.ts
export class User {
email: string;
password: string;
lastLogin: Date;
constructor(msg:string) {
this.email = "";
this.password = "";
this.lastLogin = new Date();
console.log("*** User class constructor " + msg + " ***");
}
Login() {
}
}
login.component.ts
import {Component} from "@angular/core";
import {User} from "./../../shared/user/user"
@Component({
selector: "login-component",
templateUrl: "pages/login/login.html",
styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})
export class LoginComponent {
user: User = new User("property"); // ONE
isLoggingIn:boolean;
constructor() {
this.user = new User("constructor"); // TWO
console.log("*** Login Component Constructor ***");
}
ngOnInit() {
this.user = new User("ngOnInit"); // THREE
this.user.Login();
this.isLoggingIn = true;
console.log("*** Login Component ngOnInit ***");
}
submit() {
alert("You’re using: " + this.user.email + " " + this.user.lastLogin);
}
toggleDisplay() {
this.isLoggingIn = !this.isLoggingIn;
}
}
控制台输出
JS: *** User class constructor property ***
JS: *** User class constructor constructor ***
JS: *** Login Component Constructor ***
JS: *** User class constructor ngOnInit ***
JS: *** Login Component ngOnInit ***
我找到了答案,试着把它翻译成英语: 即使在技术面试中,这个问题仍然会出现。事实上,两者之间有很大的相似之处,但也有一些不同。
构造函数是ECMAScript的一部分。另一方面,ngOnInit()是angular的概念。 即使不使用Angular,我们也可以在所有类中调用构造函数 生命周期:构造函数在ngOnInt()之前调用 在构造函数中,我们不能调用HTML元素。然而,在ngOnInit()中我们可以。 通常,服务调用在ngOnInit()中,而不是在构造函数中 来源:http://www.angular-tuto.com/Angular/Component Diff