何时使用 AngularJS `$onInit` 生命周期挂钩

When to use the AngularJS `$onInit` Life-Cycle Hook

随着 AngularJS V1.7 的发布,预分配绑定的选项已弃用并删除:

Due to 38f8c9, directive bindings are no longer available in the constructor.

To migrate your code:

  • If you specified $compileProvider.preAssignBindingsEnabled(true) you need to first migrate your code so that the flag can be flipped to false. The instructions on how to do that are available in the "Migrating from 1.5 to 1.6" guide. Afterwards, remove the $compileProvider.preAssignBindingsEnabled(true) statement.

AngularJS Developer Guide - Migrating to V1.7 - Compile

Due to bcd0d4, pre-assigning bindings on controller instances is disabled by default. We strongly recommend migrating your applications to not rely on it as soon as possible.

Initialization logic that relies on bindings being present should be put in the controller's $onInit() method, which is guaranteed to always be called after the bindings have been assigned.

AngularJS Developer Guide - Migrating from v1.5 to v1.6 - $compile

必须将代码移至 $onInit Life-Cycle Hook 的用例是什么?我们什么时候可以只留下控制器构造函数中的代码?

当代码依赖于绑定时,必须将代码移动到 $onInit 函数中,因为这些绑定在构造函数的 this 中不可用。它们在组件 class 实例化后被分配。

示例: 您有这样的状态定义:

$stateProvider.state("app", {
  url: "/",
  views: {
    "indexView": {
      component: "category"
    }
  },
  resolve: {
    myResolve: (someService) => {
      return someService.getData();
    }
  }
});

您可以像这样将 myResolve 的结果绑定到您的组件:

export const CategoryComponent = {
  bindings: {
    myResolve: "<"
  },
  controller: Category
};

如果您现在在 constructor$onInit 中注销 this.myResolve,您将看到如下内容:

constructor() {
  console.log(this.myResolve); // <-- undefined
}

$onInit() {
  console.log(this.myResolve); // <-- result of your resolve
}

因此,您的构造函数应仅包含如下构造代码:

constructor() {
  this.myArray = [];
  this.myString = "";
}

每个 angular 特定的初始化和绑定或依赖使用应该在 $onInit