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

该文件说实际上存在差异,但它没有提到差异:

角(预1.0 RC)的早期版本允许你使用this与互换$scope的方法,但是这不再是这种情况。 在scope和this $scope定义的方法的内部是可以互换的(角度将this设置为$scope ),但是在控制器构造函数中没有。

this$scope在AngularJS控制器中如何工作?


“在AngularJS控制器中this$scope如何工作的?”

简短的回答

  • this
  • 当控制器构造函数被调用时, this是控制器。
  • 当调用$scope对象上定义的函数时, this就是“函数被调用时的作用域”。 这可能(或可能不)是函数定义的$scope 。 所以,在函数内部, this$scope可能一样。
  • $scope
  • 每个控制器都有一个关联的$scope对象。
  • 控制器(构造函数)函数负责在关联的$scope上设置模型属性和函数/行为。
  • 只有在这个$scope对象上定义的方法(和父范围对象,如果原型继承在场)可以从HTML / view中访问。 例如,从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 tab控制器。 (窗格指令似乎没有require选项卡$范围的机制。)

    所以,这引出了一个问题:如果我们只能访问tabs控制器,我们如何访问标签隔离$ scope(这正是我们真正想要的)?

    那么红色虚线就是答案。 addPane()函数的“作用域”(我在这里指的是JavaScript的函数作用域/闭包)使函数可以访问标签隔离$ scope。 即,addPane()可以访问上图中的“选项卡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>
    

    ParentCtrlParentCtrl

    $scope.logThisAndScope = function() {
        console.log(this, $scope)
    }
    

    单击第一个链接将显示this$scope是相同的,因为“函数调用时的作用域”是与ParentCtrl关联的ParentCtrl

    点击第二个链接就会发现this$scope一样的,因为“函数调用时的作用域”是与ChildCtrl关联的ChildCtrl 。 所以在这里, this被设置为ChildCtrl$scope 。 在该方法中, $scope仍然是ParentCtrl的$ scope。

    小提琴

    我尽量不使用this上$范围内定义的函数中,因为它变得扑朔迷离其中$范围受到影响,尤其是考虑到NG-重复,NG-包括NG-开关和指令都可以创建自己的子作用域。


    'addPane'分配给这个的原因是因为<pane>指令。

    pane指令确实require: '^tabs' ,它将tab控制器对象从父指令中放入链接函数中。

    addPane分配给this以便pane链接功能可以看到它。 然后在pane链接函数中, addPane只是tabs控制器的一个属性,它只是tabsControllerObject.addPane。 因此,窗格指令的链接函数可以访问制表符控制器对象,因此可以访问addPane方法。

    我希望我的解释清楚。这很难解释。


    我刚刚阅读了关于两者之间差异的一个非常有趣的解释,并且越来越倾向于将模型附加到控制器,并且别名控制器将模型绑定到视图。 http://toddmotto.com/digging-into-angulars-controller-as-syntax/是文章。 他没有提到它,但是在定义指令时,如果您需要在多个指令之间共享某些内容并且不想要服务(有合法的情况下服务很麻烦),请将数据附加到父指令的控制器。 $ scope服务提供了很多有用的东西,$ watch是最明显的,但如果您只需要将数据绑定到视图,则使用模板中的普通控制器和'controller as'是很好的,并且可以说是可取的。

    链接地址: http://www.djcxy.com/p/2181.html

    上一篇: 'this' vs $scope in AngularJS controllers

    下一篇: Dependency Injection vs Factory Pattern