实例化Injectable类时未调用ngOnInit


195

解决类后为何不ngOnInit()调用Injectable

import {Injectable, OnInit} from 'angular2/core';
import { RestApiService, RestRequest } from './rest-api.service';

@Injectable()
export class MovieDbService implements OnInit {

    constructor(private _movieDbRest: RestApiService){
        window.console.log('FROM constructor()');
    }

    ngOnInit() {
         window.console.log('FROM ngOnInit()');
    }

}

控制台输出

FROM constructor()

Answers:


312

生命周期挂钩,类似于OnInit()使用指令和组件。它们不适用于其他类型,例如您的情况下的服务。从文档:

组件的生命周期由Angular本身管理。Angular会创建,渲染,创建和渲染其子级,在其数据绑定属性更改时对其进行检查,并在将其从DOM中删除之前销毁它。

指令实例和组件实例具有生命周期,因为Angular创建,更新和销毁它们。


38
因此,只需将我的ngOnInit逻辑移到Injectable类的构造函数上?我刚刚记得阅读过,无论出于何种原因,都应将任何逻辑排除在构造函数之外。
维·富勒

48
@LeviFuller是的,对于服务,您可以在构造函数中进行初始化,或者更好地使init方法从构造函数中调用(以防您稍后需要重置服务)。
萨斯加

9
不完全是,OnInit与绑定有关。当您要等待输入值解析时使用它,因为它们在构造函数中不可用。构造函数可以被多次调用。例如,当您更改路线并加载不同的组件时,它们每次都“被构造”并破坏……
Sasxa

5
在这里还值得注意的是,Sevices 可以被实例化多次,具体取决于您在providers数组中的位置。如果要使用单例服务,请将其放在主模块的中providers,如果要按组件进行服务,则将它们直接添加到组件中。
Askdesigners

4
这并非完全不正确,因为@ SBD580在他的回答中指出,ngOnDestroy需要进行注入服务
shusson

48

我不知道所有的生命周期挂钩,但是对于销毁,ngOnDestroy实际上是在提供者被销毁时(例如,由组件提供的Injectable)在Injectable上调用的。

来自 docs :

销毁指令,管道或服务时调用的生命周期挂钩。

万一有人对销毁感兴趣,请检查以下问题:


2
这样的耻辱ngOnInit不被称为:-(我真的很想做一些透明的延迟初始化魔术。如果ngOnDestroy可以称之为,我不明白为什么初始化不能做到
Simon_Weaver

3

注意:此答案仅适用于Angular组件和指令,不适用于服务。

ngOnInit(以及其他生命周期挂钩)没有为我的组件触发时,我遇到了同样的问题,大多数搜索都将我引到了这里。

问题是我在使用箭头函数语法(=>),如下所示:

class MyComponent implements OnInit {
    // Bad: do not use arrow function
    public ngOnInit = () => {
        console.log("ngOnInit");
    }
}

显然,这在Angular 6中不起作用。使用非箭头函数语法可解决此问题:

class MyComponent implements OnInit {
    public ngOnInit() {
        console.log("ngOnInit");
    }
}

可注入类是服务,而不是组件。OP询问服务。尽管从语言POV看您的答案可能是正确的,但它不能回答此问题。您应该删除它。
安德鲁·菲利普

@AndrewPhilips虽然我的用例与OP略有不同,但在Google中搜索“未调用ngOnInit”会引人关注。我这样做的目的不是帮助OP,而是帮助其他70,000+可能有类似问题的观众ngOnInit
AJ理查森

很公平。我相信我已经看到了SO Q&A,其中作者提出问题,然后回答他们自己的问题。作为新的Angular程序员,您的答案会让我在两周前感到困惑。从SO和NG的角度来看,我认为您的回答都值得提出自己的问题,因此不要删除,而是“重新分类”。谁知道?也许它可以触及更广泛的受众。干杯。
安德鲁·菲利普

1
很有道理-我修改了答案,以明确表示这不是针对服务的。
AJ理查森


0
import {Injectable, OnInit} from 'angular2/core';
import { RestApiService, RestRequest } from './rest-api.service';
import {Service} from "path/to/service/";

@Injectable()
export class MovieDbService implements OnInit {

userId:number=null;

constructor(private _movieDbRest: RestApiService,
            private instanceMyService : Service ){

   // do evreything like OnInit just on services

   this._movieDbRest.callAnyMethod();

   this.userId = this.instanceMyService.getUserId()


}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.