Angular.js: 控制器挂钩顺序(在 $onInit 之前调用 $onChanges)

创建于 2016-12-16  ·  9评论  ·  资料来源: angular/angular.js

您要请求功能还是报告错误
我不知道这是想要的还是错误的

目前的行为是什么?
第一个$onChanges调用在$onInit调用之前完成。
使用 angular 1.6 默认配置 (preassign = false),最好在$onInit函数中初始化控制器状态,因为在构造函数中还无法访问绑定。

什么是预期行为?
我认为首先调用$onInit会更合乎逻辑。
当控制器没有完全初始化时,Angular 不应该做任何事情。

改变行为的动机/用例是什么?
如果我们在$onChanges函数中使用应该在$onInit函数中创建的对象; 我们将在第一次调用中出错,因为控制器尚未初始化。
一个解决方案可能是在构造函数中初始化这些对象,但我们将在两个不同的地方初始化控制器......

哪些版本的 Angular 以及哪些浏览器/操作系统受到此问题的影响? 还请使用最新的稳定版和快照版 (https://code.angularjs.org/snapshot/) 进行测试。
角度 1.6 版本

works as expected

最有用的评论

这是有意的(主要是为了匹配 Angular 2+ 的行为)。 如果你已经错过了它,你可以检查它是否是第一(预$的OnInit)调用$onChanges ,通过检查返回值isFirstChange()的任何方法SimpleChange对象:

{
  ...
  bindings: {foo: '<'},
  controller: function SomeController() {
    this.$onChanges = function(changes) {
      if (changes.foo.isFirstChange()) {
        // `$onInit()` has not been called yet...
      }
    };
  }
}

#

我承认我的第一反应是一样的。 从心智模型的角度来看,更容易认为$onInit()是控制器中发生的第一件事; 然后$onChanges()$onChanges()$onChanges()最后$onDestroy()

但是,如果您考虑一下,在调用$onInit之前需要评估绑定并将其分配给控制器实例。 并且通过这样做,检测到(以前未定义的)值的变化,这反过来需要通过$onChanges

结束,因为这按预期工作(或至少按预期工作:眨眼:)。

所有9条评论

这是有意的(主要是为了匹配 Angular 2+ 的行为)。 如果你已经错过了它,你可以检查它是否是第一(预$的OnInit)调用$onChanges ,通过检查返回值isFirstChange()的任何方法SimpleChange对象:

{
  ...
  bindings: {foo: '<'},
  controller: function SomeController() {
    this.$onChanges = function(changes) {
      if (changes.foo.isFirstChange()) {
        // `$onInit()` has not been called yet...
      }
    };
  }
}

#

我承认我的第一反应是一样的。 从心智模型的角度来看,更容易认为$onInit()是控制器中发生的第一件事; 然后$onChanges()$onChanges()$onChanges()最后$onDestroy()

但是,如果您考虑一下,在调用$onInit之前需要评估绑定并将其分配给控制器实例。 并且通过这样做,检测到(以前未定义的)值的变化,这反过来需要通过$onChanges

结束,因为这按预期工作(或至少按预期工作:眨眼:)。

非常感谢您的回答,现在更清楚了:)

我知道这是故意的,如果我们在 $onInit() 中注册 $onChanges() 函数的定义如何。

@bharatpatil ,它应该在 AngularJS (1.x.) 中工作,但不能在 Angular (2+) 中工作。

如果 (changes.foo.isFirstChange()) {
// $onInit()还没有被调用...
}

@gkalpak我认为这个论点是错误的。 binding.isFirstChange()方法只保证第一次调用相关绑定。 想想在服务调用花费太长时间后初始化的绑定。 在这种情况下, controller.$onInit方法应该之前调用controller.$onChanges方法。 我错了吗?

绑定总是在开头有一个值(可能是undefined ),它总是不同于它的预初始化值。 因此, $onChanges()始终会叫changes.foo之前调用$onInit()

绑定在初始化之前可以有一个值是没有逻辑意义的。 那是单词初始化(设置初始值)的字典定义。 如果没有初始值,则无法更改某些内容。 我认为这里的命名完全错误且不自然。

我不记得我没有被迫写这样的代码的情况:

$onChanges(changesObj: { [index: string]: angular.IChangesObject; })  {
   if (!this.isInitialized) return;
   ...
}

在“初始化”之前调用“更改”没有任何意义。

与 Angular 的课程相当……为什么有人会期望 init 在更改之前发生?

此页面是否有帮助?
0 / 5 - 0 等级