“如何this
和$scope
在AngularJS控制器的工作?”
简短答案:
this
- 调用控制器构造函数时,
this
就是控制器。
- 调用在
$scope
对象上定义的函数时,this
是“调用该函数时有效的作用域”。这可能是(也可能不是!)$scope
函数定义的依据。所以,在函数内部,this
并且$scope
可能不相同。
$scope
- 每个控制器都有一个关联的
$scope
对象。
- 控制器(构造函数)功能负责在其关联的上设置模型属性和功能/行为
$scope
。
- 仅
$scope
可以从HTML /视图访问在此对象(和父作用域对象,如果正在进行原型继承的情况)上定义的方法。例如,来自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
tabs控制器。(对于require
$ scope选项卡,pane指令似乎没有机制。)
因此,这就引出了一个问题:如果我们仅有权使用tabs控制器,那么我们如何获得对选项卡的隔离$ scope(这是我们真正想要的)?
好吧,红色虚线就是答案。addPane()函数的“作用域”(我在这里指的是JavaScript的函数作用域/闭包)使函数可以访问制表符隔离$ scope。即,由于在定义addPane()时创建了一个闭包,因此addPane()可以访问上图中的“选项卡IsolateScope”。(如果改为在选项卡的$ scope对象上定义addPane(),则panel指令将无法访问此函数,因此它将无法与选项卡的$ 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
(Solely)有
$scope.logThisAndScope = function() {
console.log(this, $scope)
}
单击第一个链接将显示this
和$scope
相同,因为“ 调用函数时有效的作用域”是与关联的作用域ParentCtrl
。
单击第二个链接将显示this
,$scope
并且不相同,因为“ 调用函数时有效的作用域”是与关联的作用域ChildCtrl
。所以在这里,this
被设置为ChildCtrl
的$scope
。在方法内部,$scope
仍然ParentCtrl
是$ scope。
小提琴
我试着不要this
在$ scope上定义的函数中使用它,因为这会影响哪个$ scope,尤其是考虑到ng-repeat,ng-include,ng-switch和指令都可以创建自己的子作用域,这使我感到困惑。