我想了解为什么当在重复的项目上使用带有特定控制器的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
答案 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用作系统中的消息代理。
关于具体细节,这与指令的范围有关,处理此代码的更好方法(对于可能偶然发现此问题的其他代码)如下:
<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;
这减轻了范围界定的问题,并且明确允许在指令中访问适当的控制器。
答案 2 :(得分:0)
根据你想要广播的评论,你可以使用这样的函数并从孩子那里调用它:
// in MainController:
$scope.broadcastMain = function(message) {
$scope.$broadcast(message);
};
然后该函数被继承,但它的闭包将$scope
与其创建的范围相同,因此您可以使用$scope.broadcast()
来获取其子项。 (codepen)