想象一下购物车的控制器:
app.controller('CartCtrl', function ($scope) {
$scope.data = [
{
id:0,
title:'article1'
},
{
id:1,
title:'article2'
}
];
$scope.countItems = function(){
var num = 0;
for(var i in $scope.data){
num++
}
return num;
}
});
它在页面的某处使用:
<ul ng-controller="CartCtrl">
<li ng-repeat="item in data">{{item.title}}</li>
</ul>
其他地方我想显示购物车中的商品数量:
<div cart-item-number>{{countItems()}}</div>
要连接数据,请使用指令:
app.directive('cartItemNumber', function() {
return {
restrict: 'A',
controller: 'CartCtrl'
};
});
在页面加载时显示正确的数字。但是,如果我从数据对象中删除或添加项目,则 cart-item-number不会更新。
如何解决此问题?
答案 0 :(得分:2)
所以ng-controller="CartCtrl"
和controller: 'CartCtrl'
是两个不同的对象。在指令声明中,您为指令指定控制器。当您的应用程序启动时,它们都会使用相同的数据进行初始化,因此似乎可以始终如一地工作。
如果你想显示CartCtrl
范围内的项目数量而不是你不需要使用指令(顺便说一下,最好只使用data.length
)。如果您打算将其显示在范围之外,则必须创建某种形式的通信。
或者至少在范围的层次结构中将cart
移到更高的位置 - 当然,$rootScope
它会在您的应用程序中随处可见(除非您使用的是isolated scope
)。
答案 1 :(得分:2)
首先,原因是因为您没有在同一范围内工作。请考虑以下示例:
<body>
<ul ng-controller="CartCtrl">
<li ng-repeat="item in data">{{item.title}}</li>
</ul>
<div cart-item-number>{{countItems()}}</div>
</body>
该指令在RootScope上注册,而ngController是子范围。因此,您最终会有两个数据副本。我建议您使用AngularJS Batarang Chrome插件来显示上述范围和模型。
将上述示例中的ng-controller移动到body,您将看到预期的行为。
然而,您使用控制器的方式被认为是不好的做法。指令控制器的唯一目的是将API暴露给其他指令,用于指令通信的指令。其中“普通”控制器(在ngController和路由中使用)用于扩充范围并向范围对象添加行为。
如果需要在“普通”控制器和指令之间进行通信,则应使用中介服务(让控制器和指令都依赖于此服务),或使用$ scope事件,如$ scope。$ broadcast和$ scope。$ emit在它们之间进行通信。这将控制器与指令分离,并允许可重复使用的组件和简单的测试。