AngularJS控制器中的'this'与$ scope

阿列克谢波罗宁

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,代码将中断。

该文档说实际上存在区别,但是没有提及区别是什么:

以前的Angular版本(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从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”控制器构造函数后,我们将具有以下内容:

Tabs控制器构造函数之后

黑色虚线表示原型继承-一个隔离范围原型从Scope继承(它并不是从HTML中遇到指令的有效范围继承的原型。)

现在,窗格指令的链接功能希望与tabs指令通信(这实际上意味着它需要以某种方式影响选项卡隔离$ scope)。可以使用事件,但是另一种机制是使面板指令requiretabs控制器。(对于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和指令都可以创建自己的子作用域,这令人感到困惑。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在AngularJS中的不同控制器中访问$ scope

在angularjs控制器的打字稿代码中处理$ scope

别名AngularJS $ scope对象在控制器中

Angularjs“控制器为”或“ $ scope”

在指令/控制器中绑定$ scope

AngularJS:通过属性从TD中的指令获取文本并通过控制器$ scope中的引发事件?

在SpringMVC控制器层中,@Scope(“ prototype”)与@Scope(“ singleton”)

如何在AngularJS中与另一个控制器共享$ scope变量?

AngularJS如何在2个或更多控制器中解析对$ scope变量的调用?

AngularJS 控制器 $scope 在 ng-if 指令中不起作用

AngularJS控制器as和this而不是$ scope在指令中调用$ apply

从同一控制器Angularjs中的另一个方法访问$ scope变量

AngularJS:指令将对象添加到 $scope 但在控制器中未定义

scope()函数在AngularJS控制器中返回未定义

如何从Angularjs中的控制器向$ scope.master对象添加一些变量

AngularJS:为什么在我的ES6控制器中未定义$ scope?

AngularJS $ scope.foo设置了服务,但后来在同一控制器中未定义

AngularJS:使用$ scope。$ watch与控制器作为语法

AngularJS-将$ scope传递给控制器

在AngularJS控制器和指令中使用“ this”而不是“ scope”

来自$ scope的AngularJS以编程方式获取表单控制器

AngularJS 1 在一个控制器中内联注入 $scope 会破坏第二个控制器

AngularJs单元测试失败,因为Karma无法识别$ scope。$ on在控制器中的侦听器上

在控制器函数的回调中修改$ scope

$ scope.data在控制器中未定义

将控制器$ scope绑定到服务中的对象

$ scope在控制器中未定义

角$ scope变量未在控制器中更新

没有$ scope的控制器