【问题标题】:NG1: Class controller constructor vs $onInit for variable initialization and method bindingsNG1:用于变量初始化和方法绑定的类控制器构造函数与 $onInit
【发布时间】:2017-08-03 15:35:16
【问题描述】:

在将此问题标记为重复之前...我知道您在想什么,这已被问过无数次,但并不完全正确。

我在研究期间从各种来源(包括官方文档,以及 Angular Guru 和传道者)知道$onInit 块通常保留用于 依赖于 Angular 完成所有绑定的初始化工作/逻辑。

然而,变量初始化并不真正符合这个“工作/逻辑”的定义。特别是其中没有任何角度逻辑的变量。因此,ES6 构造函数似乎更适合变量初始化。对于需要词法绑定范围的回调方法绑定也是如此:

class myController() {
  constructor() {
    this.myVariableOne = 1,
    this.myVariableTwo = 2,
    this.myVariableThree = 3;

    this.myMethod = this.myMethod.bind(this);
  }

  $onInit() { }

  myMethod() {
    console.log(this.myVariableOne, this.myVariableTwo, this.myVariableThree);
  }
}

虽然这看起来很适合遵循“角度方式”做事,仅使用$onInit 块进行初始化工作/逻辑,我也看到很多人说角度控制器类构造函数只能用于依赖注入设置。

所以,这让我很困惑。构造函数似乎是最适合变量初始化和方法绑定的块,而$onInit 似乎并不真正适合该角色,但目前还不清楚我应该使用什么。有人可以帮我弄清楚我应该将变量定义和方法绑定放在哪里吗?

【问题讨论】:

  • 上面的代码中没有this.myVariableOne等
  • 哎呀,抱歉,已修复。

标签: javascript angularjs controller ecmascript-6 angular1.6


【解决方案1】:

这完全取决于这些属性是什么。对于初始静态值(如上面的代码),构造函数是合适的位置。

$onInit 用于 DOM 和数据绑定初始化代码,它是 1.5 之前的 pre-link 函数的直接对应物。出于可测试性原因,其他初始化代码也可以放在$onInit 中。

考虑到初始化时调用了一些实例(不是原型)方法:

constructor() {
  this.method = () => ...;
}

$onInit() {
  this.method();
}

可以像这样测试

const ctrl = $controller('...');
spyOn(ctrl, 'method').and...;
ctrl.$onInit();
expect(ctrl.method).toHaveBeenCalled();

如果在构造函数中调用它,就不可能窥探或模拟它。

这个问题对非模块化 ES5 应用的影响更大,因为它们的方法通常被定义为this.method = ...,而控制器prototype 无法轻易访问,因为无法导入控制器构造函数。

【讨论】:

  • 感谢您的意见!我同意$onInit 通常用于绑定初始化代码,但是,在什么上下文中绑定?因为我知道它用于绑定依赖于角度绑定的代码。但是,.bind() 的作用域绑定听起来更像是非角度初始化的一部分,在控制器构造函数中看起来更好。
  • 我已添加说明。 $onInit 用于 data 绑定。 this.myMethod.bind(this) 绝对属于构造函数。越早完成越好。
【解决方案2】:

我同意您的总体评价。我的构造函数很轻,但是如果我在实例化时做的事情与角度无关,我一直在将它们放入构造函数中。我和他们没有任何问题。我只是查看了其中的十几个,除了初始化属性并将依赖注入分配给属性之外,我基本上什么也没做。我只有一个控制器,它可以调用任何外部代码。

关于 Angular 1.5 的文章很少。如果你还没有看过这个:https://toddmotto.com/rewriting-angular-styleguide-angular-2 我认为这是“现代 angularjs”最好的风格指南。

【讨论】:

  • 谢谢!另外,我已经是 Todd Motto 和 John Papa 的追随者,但是 John Papa 在 Angular 1 中对类的使用非常有限,而 Todd Motto 建议应该将 $onInit 用于所有内容,包括变量初始化。然而,这使$onInit 膨胀,并且在阅读了很多它的用途之后(不是来自 ng-docs,因为正如你所说的那样它们非常稀疏),它似乎不太合适。但感谢您的意见!
  • @sgarcia.dev Todd Motto 是一个不错的开发者,但他在这里弄错了。这与其他担忧相矛盾。 IE。在 TypeScript 中(在 A1 中也是)将 props 定义为类和构造函数是很自然的,但在这种情况下,它们将在构造函数中初始化。
  • @sgarcia.dev 我一直习惯于将我能从 OnInit 到 postLink 的内容推迟到 postLink,以使我的 onInit 尽可能轻松。
最近更新 更多