在AngularJS 主页的“创建组件” 部分中 ,有以下示例:
controller: function($scope, $element) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.push(pane);
}
}
注意如何将select
方法添加到$scope
,但是addPane
方法被添加this
。如果我将其更改为$scope.addPane
,则代码会中断。
文档说实际上存在差异,但没有提到差异是什么:
角(预 1.0 RC)的早期版本允许你使用
this
与互换$scope
的方法,但是这不再是这种情况。里面对范围定义的方法this
和$scope
是可以互换(角套this
以$scope
),而不是其他你的控制器构造函数中。
this
和$scope
如何在 AngularJS 控制器中工作?
“
this
和$scope
如何在 AngularJS 控制器中工作?”
简短回答 :
this
this
是控制器。 $scope
对象上定义的函数时, this
是 “调用函数时生效的范围”。这可能(或可能不是!)是定义函数的$scope
。因此,在函数内部, this
和$scope
可能不一样。 $scope
$scope
对象。 $scope
上设置模型属性和函数 / 行为。 $scope
对象上定义的方法(以及父范围对象,如果是原型继承)。例如,来自ng-click
,过滤器等。 答案很长 :
控制器函数是 JavaScript 构造函数。当构造函数执行时(例如,当视图加载时), this
(即 “函数上下文”)被设置为控制器对象。所以在 “tabs” 控制器构造函数中,当创建 addPane 函数时
this.addPane = function(pane) { ... }
它是在控制器对象上创建的,而不是在 $ scope 上创建的。视图无法看到 addPane 函数 - 它们只能访问 $ scope 上定义的函数。换句话说,在 HTML 中,这将不起作用:
<a ng-click="addPane(newPane)">won't work</a>
执行 “tabs” 控制器构造函数后,我们有以下内容:
黑色虚线表示原型继承 - 原型继承自Scope的隔离范围。 (它没有原型地继承 HTML 中遇到指令的有效范围。)
现在,窗格指令的链接函数想要与 tabs 指令进行通信(这实际上意味着它需要以某种方式影响选项卡隔离 $ scope)。可以使用事件,但另一种机制是使窗格指令require
选项卡控制器。 (似乎没有窗格指令require
选项卡 $ scope 的机制。)
因此,这就引出了一个问题:如果我们只能访问选项卡控制器,那么我们如何访问选项卡隔离 $ scope(这是我们真正想要的)?
嗯,红色虚线就是答案。 addPane()函数的 “范围”(我指的是 JavaScript 的函数范围 / 闭包)给函数访问选项卡隔离 $ scope。即,addPane()可以访问上图中的 “tabs IsolateScope”,因为在定义 addPane()时创建了一个闭包。 (如果我们在选项卡 $ scope 对象上定义了 addPane(),则窗格指令将无法访问此函数,因此它无法与选项卡 $ scope 通信。)
要回答你问题的另一部分: how does $scope work in controllers?
:
在 $ scope 中定义的函数内, this
其设置为 “调用函数时 / 当有效的 $ scope”。假设我们有以下 HTML:
<div ng-controller="ParentCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
<div ng-controller="ChildCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
</div>
</div>
并且ParentCtrl
( ParentCtrl
)有
$scope.logThisAndScope = function() {
console.log(this, $scope)
}
单击第一个链接将显示this
和$scope
是相同的,因为 “ 调用函数时生效的范围” 是与ParentCtrl
关联的范围。
单击第二个链接将显示this
并且$scope
不相同,因为 “ 调用函数时生效的范围” 是与ChildCtrl
关联的范围。所以在这里, this
被设置为ChildCtrl
的$scope
。在方法内部, $scope
仍然是ParentCtrl
的 $ scope。
我尽量不使用this
上 $ 范围内定义的函数中,因为它变得扑朔迷离其中 $ 范围受到影响,尤其是考虑到 NG - 重复,NG - 包括 NG - 开关和指令都可以创建自己的子作用域。
“addPane” 分配给它的原因是因为<pane>
指令。
pane
指令确实require: '^tabs'
,它将来自父指令的 tabs 控制器对象放入 link 函数中。
addPane
被分配给this
以便pane
链接功能可以看到它。然后在pane
链接函数中, addPane
只是tabs
控制器的一个属性,它只是 tabsControllerObject.addPane。因此,pane 指令的链接功能可以访问 tabs 控制器对象,从而访问 addPane 方法。
我希望我的解释很清楚...... 这很难解释。
我刚刚阅读了关于两者之间差异的一个非常有趣的解释,并且越来越倾向于将模型附加到控制器并且将控制器别名为控制器以将模型绑定到视图。 http://toddmotto.com/digging-into-angulars-controller-as-syntax/是这篇文章。他没有提到它,但是在定义指令时,如果你需要在多个指令之间共享某些内容并且不需要服务(存在服务麻烦的合法情况),那么将数据附加到父指令的控制器。 $ scope 服务提供了大量有用的东西,$ watch 是最明显的,但如果你只需要将数据绑定到视图,那么在模板中使用普通控制器和'controller as' 是可以的,并且可以说是更好的选择。