当使用ng-repeat时,Angular $ parent和$ parent。$ parent是相同的控制器

时间:2014-12-26 22:09:30

标签: angularjs angularjs-scope parent

我想了解为什么当在重复的项目上使用带有特定控制器的ng-repeat时,该项目的父项和该项目的祖父是同一个控制器。我期待祖父成为父控制器的父母,而不是同一个控制器。

这里的代码澄清了这个

HTML

<div ng-controller="MainController">
  {{name}}
  <div ng-controller="SecondController">
  {{name}}
    <ul>
      <li ng-repeat="item in list" ng-controller="ItemController">
         {{item.name}} {{$parent.name}} {{myDad}} {{myGrandpa}}
      </li>
    </ul>
    <div ng-controller="ThirdController">
         {{name}} {{$parent.name}} {{myDad}} {{myGrandpa}}
    </div>
  </div>
</div>

JS

angular.module('app', []);


angular.module('app')
  .controller('MainController', function($scope) {
  $scope.name = "MainController";
 })
.controller('SecondController', function($scope) {
  $scope.name = "SecondController";
  $scope.list = [
   {'name': 'aaa'}
  ];
})
.controller('ItemController', function($scope) {
  $scope.name = "ItemController";
  $scope.myDad = $scope.$parent.name;
  $scope.myGrandpa = $scope.$parent.$parent.name;
})
.controller('ThirdController', function($scope) {
  $scope.name = "ThirdController";
  $scope.myDad = $scope.$parent.name;
  $scope.myGrandpa = $scope.$parent.$parent.name;
});

这是CodePen

3 个答案:

答案 0 :(得分:4)

在Angular中,$ scope继承而不是控制器。

由ng-controller创建的每个控制器都会创建一个新的$ scope(childScope),它继承自它所存在的$ scope。我想你可能想要阅读这个answer以了解$ scope是如何继承的(原型)继承)。

请注意,您不必使用“$ parent”来获取父$ scope的名称,例如,如果要从ItemController中删除$ scope.name并尝试绑定{{name}您的模板将被编译和链接,{{name}}的值将在您的示例中为“SecondController”。

关于$ broadcast,你应该尽量避免使用$ rootScope。$ broadcast,因为它会向你的应用程序中的所有$ scope发送一个事件。我不确定你的用例是什么,但是如果你想执行一个在你的“MainController”中定义的方法,你可以调用它来举例如

angular.module('app', []);


angular.module('app')
  .controller('MainController', function($scope) {
  $scope.name = "MainController";
  $scope.doSomething = function() {
    console.log("Do it");
  }
 })
.controller('SecondController', function($scope) {
  $scope.name = "SecondController";
  $scope.list = [
   {'name': 'aaa'}
  ];
})
.controller('ItemController', function($scope) {
  $scope.name = "ItemController";
  $scope.myDad = $scope.$parent.name;
  $scope.myGrandpa = $scope.$parent.$parent.name;
  $scope.clickItem = function() {
     console.log("Item clicked");
     $scope.doSomething(); // The method from "MainController" will be executed unless ItemController is isolated 
  }
})
.controller('ThirdController', function($scope) {
  $scope.name = "ThirdController";
  $scope.myDad = $scope.$parent.name;
  $scope.myGrandpa = $scope.$parent.$parent.name;
});

答案 1 :(得分:0)

回答您的评论问题,是的,您应该将$ rootScope用作系统中的消息代理。

关于具体细节,这与指令的范围有关,处理此代码的更好方法(对于可能偶然发现此问题的其他代码)如下:

&#13;
&#13;
<div ng-controller="MainController as main">
  {{main.name}}
  <div ng-controller="SecondController as second">
  {{second.name}}
    <ul>
      <li ng-repeat="item in list" ng-controller="ItemController as item">
         {{item.name}} {{second.name}} {{myDad}} {{myGrandpa}}
      </li>
    </ul>
    <div ng-controller="ThirdController as third">
         {{name}} {{third.name}} {{myDad}} {{myGrandpa}}
    </div>
  </div>
</div>
&#13;
&#13;
&#13;

这减轻了范围界定的问题,并且明确允许在指令中访问适当的控制器。

答案 2 :(得分:0)

根据你想要广播的评论,你可以使用这样的函数并从孩子那里调用它:

// in MainController:
$scope.broadcastMain = function(message) {
    $scope.$broadcast(message);
};

然后该函数被继承,但它的闭包将$scope与其创建的范围相同,因此您可以使用$scope.broadcast()来获取其子项。 (codepen