我最近开始学习和使用AngularJS,但我仍然不清楚一些概念。
我的问题是:在我的应用程序中,我有一个控制器,它在初始化后立即使用$http
从后端检索数据。根据CodeSchool关于Angular的优秀教程,我想出了这个:
app.controller("agentController", function ($http) {
var agentsCtrl = this;
agentsCtrl.agents = [];
$http.get("getAgents").success(function (data) {
agentsCtrl.agents = data;
});
...
HTML:
<div ng-controller="agentController as agentCtrl">
<div ng-repeat="agent in agentCtrl.agents">
...
这很好,但我不清楚为什么需要使用this
将控制器声明为其内部的变量。据我所知,这是因为通过这样做,我可以在$http
服务中调用它,其中this
关键字将返回错误的范围。这是正确的吗?
我发现这也有效:
app.controller("agentController", function ($http, $scope) {
$scope.agents = [];
$http.get("getAgents").success(function (data) {
$scope.agents = data;
});
HTML:
<div ng-controller="agentController as agentCtrl">
<div ng-repeat="agent in agents">
...
我想这是有效的,因为我显式地注入了作用域并在服务中使用它。此外,HTML现在略有不同。在第一种情况下,我需要显式调用agentCtrl.agents
,而对于scope,只需调用agents
。这仍然是因为变量现在是在作用域上声明的,而不是在控制器上声明的?这是正确的吗?
在类似情况下使用的最佳实践是什么?
谢谢!
您正在询问两种不同的方法-"Controller as"或"$scope"。
$scope
范围绑定的原始用法是:
<div ng-controller="MainController">
{{ someObj.someProp }}
</div>
app.controller('MainController', function ($scope) {
$scope.someObj = {
someProp: 'Some value.'
};
});
"控制器为"
使用此技术,您可以按如下方式使用绑定:
<div ng-controller="MainController as main">
{{ main.someProp }}
</div>
app.controller('MainController', function () {
this.someProp = 'Some value.'
});
两者都有效,都很好。主要区别在于偏好。
尽管如此,大多数社区还是更喜欢"控制器",为什么?
- 可读-您可以始终查看DOM元素并了解scope的模型绑定到什么
- 可测试性-不必注入$scope使测试代码稍微容易一些
- 更适合angular 2.0的愿景,在该愿景中,控制器更像是一个构造函数,而不是一个向$scope添加内容的函数
问题1:
您必须保存对作用域var agentsCtrl = this
的引用,因为您正在创建一个用作回调的匿名函数。当您这样做时,上下文变量(this
)将是窗口。
app.controller("agentController", function ($http) {
// this == your controller
var agentsCtrl = this;
$http.get("getAgents").success(function (data) {
// Anonymous function
// this == Window Object
});
});
问题2:
$scope是应用程序控制器和视图之间的粘合剂。您可以将其引用为全局变量,您可以从视图和控制器访问该全局变量。
$scope.agents = []; // From controller
和
{{ agents }} // From view (you don't need to specify the $scope variable)
我更喜欢给控制器一个别名,并在我的HTML中使用它,就像你在中所做的那样
<div ng-controller="agentController as agentCtrl">
<div ng-repeat="agent in agents">
...
但这两种方法都是正确的,而且会很好地发挥作用。
this关键字是上下文关键字,当在控制器内的函数中使用时,可能会更改其上下文。捕捉这方面的上下文可以避免遇到这个问题。
例如:
app.controller('MainCtrl', function() {
this.test = 'test';
angular.forEach(testArray, function (item) {
console.debug(this.test);
});
});
this.test未定义,因为其范围已更改。
Plunkr
使用变量修复它:
app.controller('MainCtrl', function() {
var vm = this;
vm.test = 'test';
var testArray = [
1, 2, 3, 4
];
angular.forEach(testArray, function (item) {
console.debug(vm.test);
});
});
Plunkr
原始声明摘自John Papa的风格指南
这是为了回答您对Ben Diamant答案的评论。
不太传统的别名语法(as Alias
)简化了代码,并可能使您对阅读代码的人所做的事情更加清晰。
来自ng控制器规格:
使用
controller as
当多个控制器应用于一个元素时,可以清楚地看到您正在访问模板中的哪个控制器。
如果将控制器编写为类,则可以更容易地访问将出现在作用域上的属性和方法,来自控制器代码内部。
- 因为总有一个。在绑定中,您不必担心原型继承屏蔽基元
还可以看看这篇关于别名语法优势的精彩解释。
在这些优点中,最重要的一点是别名语法允许您进行
请咨询我们希望咨询的控制器,并停止担心范围继承的微妙之处。
我希望它能有所帮助。