NG1:Class 控制器构造函数与 $onInit 用于变量初始化和方法绑定
NG1: Class controller constructor vs $onInit for variable initialization and method bindings
在将此问题标记为重复之前...我知道您在想什么,这个问题已被问过无数次,但不完全是。
我在研究期间从各种来源(包括官方文档,以及 Angular 大师和布道者)得知 $onInit
块通常保留用于 初始化 work/logic 依赖于 angular 完成所有绑定.
然而,变量初始化并不真正符合这个 "work/logic" 定义。特别是其中没有任何 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);
}
}
虽然这看起来很好地遵循 "the angular way" 的做事,只要使用 $onInit
块进行初始化 work/logic,我也看到很多人说angular 控制器 class 构造函数 应该只用于依赖注入设置 .
所以,这让我很困惑。构造函数似乎是最适合变量初始化和方法绑定的块,而 $onInit
似乎并不适合这个角色,但我真的不清楚我应该使用什么。有人可以帮我弄清楚我应该把我的变量定义和方法绑定放在哪里吗?
这完全取决于这些属性是什么。对于初始静态值(如上面的代码),构造函数是合适的地方。
$onInit
用于 DOM 和数据绑定初始化代码,它是 pre-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
,因为无法导入控制器构造函数。
我同意你的总体评价。我让我的构造函数非常轻巧,但如果我在实例化时做的事情实际上与 angular 无关,我一直将它们放入构造函数中。我对他们没有任何问题。我只看了其中的十几个,除了初始化属性和为属性分配依赖注入外,我基本上什么都没做。我只有一个控制器,它可以调用任何外部代码。
关于 angular 1.5 的文章很少。如果您还没有看过这个:https://toddmotto.com/rewriting-angular-styleguide-angular-2 我认为这是 "modern angularjs."
最好的风格指南
在将此问题标记为重复之前...我知道您在想什么,这个问题已被问过无数次,但不完全是。
我在研究期间从各种来源(包括官方文档,以及 Angular 大师和布道者)得知 $onInit
块通常保留用于 初始化 work/logic 依赖于 angular 完成所有绑定.
然而,变量初始化并不真正符合这个 "work/logic" 定义。特别是其中没有任何 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);
}
}
虽然这看起来很好地遵循 "the angular way" 的做事,只要使用 $onInit
块进行初始化 work/logic,我也看到很多人说angular 控制器 class 构造函数 应该只用于依赖注入设置 .
所以,这让我很困惑。构造函数似乎是最适合变量初始化和方法绑定的块,而 $onInit
似乎并不适合这个角色,但我真的不清楚我应该使用什么。有人可以帮我弄清楚我应该把我的变量定义和方法绑定放在哪里吗?
这完全取决于这些属性是什么。对于初始静态值(如上面的代码),构造函数是合适的地方。
$onInit
用于 DOM 和数据绑定初始化代码,它是 pre-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
,因为无法导入控制器构造函数。
我同意你的总体评价。我让我的构造函数非常轻巧,但如果我在实例化时做的事情实际上与 angular 无关,我一直将它们放入构造函数中。我对他们没有任何问题。我只看了其中的十几个,除了初始化属性和为属性分配依赖注入外,我基本上什么都没做。我只有一个控制器,它可以调用任何外部代码。
关于 angular 1.5 的文章很少。如果您还没有看过这个:https://toddmotto.com/rewriting-angular-styleguide-angular-2 我认为这是 "modern angularjs."
最好的风格指南