【问题标题】:ngOnInit not being called when Injectable class is Instantiated实例化 Injectable 类时未调用 ngOnInit
【发布时间】:2016-05-08 17:35:27
【问题描述】:

为什么Injectable 类被解析后不调用ngOnInit()

代码

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()

【问题讨论】:

    标签: javascript angular typescript


    【解决方案1】:

    Lifecycle hooksOnInit() 一样,可用于指令和组件。它们不适用于其他类型,例如您的服务。来自文档:

    组件的生命周期由 Angular 自己管理。 Angular 创建它,渲染它,创建和渲染它的子节点,当它的数据绑定属性发生变化时检查它,并在从 DOM 中删除它之前销毁它。

    指令和组件实例在 Angular 创建、更新和销毁它们时具有生命周期。

    【讨论】:

    • 那么简单地将我的ngOnInit 逻辑移动到Injectable 类的构造函数中?我只记得读过,无论出于何种原因,您都应该将任何逻辑排除在构造函数之外。
    • @LeviFuller 是的,对于服务,您可以在构造函数中进行初始化,或者更好地创建 init 方法并从构造函数中调用它(以防您稍后需要重置服务)。
    • 不完全是,OnInit 与绑定有关。当您想要等待解析输入值时使用它,因为它们在构造函数中不可用。构造函数可以被多次调用。例如,当您更改路线并加载不同的组件时,它们每次都会“构建”并销毁......
    • 这里还值得注意的是,服务可以多次实例化,具体取决于您将它们包含在providers 数组中的位置。如果你想要一个单例服务,把它放在你的主模块的providers,如果你想要每个组件的服务,直接把它们添加到组件中。
    • 这并不完全不正确,因为@SBD580 在他的回答中指出,ngOnDestroy 被称为注入服务
    【解决方案2】:

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

    来自docs :

    当指令、管道或服务被销毁时调用的生命周期钩子。

    以防万一有人对破坏感兴趣,请查看this问题:

    【讨论】:

    • 不调用 ngOnInit 真是太可惜了 :-( 我真的很想做一些透明的延迟初始化魔术。如果可以调用 ngOnDestroy 我不明白为什么 init 不能
    【解决方案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 的用例略有不同,但谷歌搜索“未调用 ngOnInit”会导致人们来到这里。我的这个答案的目标不是帮助 OP,而是帮助其他 70,000 多名可能对ngOnInit 有类似问题的观众。
    • 很公平。我相信我看过 SO Q&A,作者提出问题然后回答他们自己的问题。作为一个新的 Angular 程序员,两周前你的回答会让我感到困惑。从 SO 和 NG 的角度来看,我认为您的答案值得提出自己的问题,因此没有被删除,而是“重新分类”。谁知道?也许它可能会接触到更广泛的受众。干杯。
    • 有道理 - 我编辑了我的答案以明确表示这不适用于服务。
    【解决方案4】:

    一旦我的 dataService 被初始化,我必须调用一个函数,相反,我在构造函数中调用它,这对我有用。

    【讨论】:

      【解决方案5】:
      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()
      
      
      }
      

      【讨论】:

      • 这个问题是 "callAnyMethod" 只能是 synchoronous 方法,不能是 await'ed...
      【解决方案6】:

      添加@Sasxa 的回答

      Injectables 中,您通常可以使用class,将初始代码放入constructor 而不是使用ngOnInit(),它可以正常工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        • 2015-09-18
        • 2021-06-03
        • 2016-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多