我有这样的结构(非常简化):
<div ng-controller="MainCtrl">
<div>Views and other stuff</div>
<div ng-controller="MyCtrl">
<div ng-repeat="item in $root.items track by $index">
{{item.id}}
</div>
<div>
Total value: {{totVal}}
</div>
</div>
</div>
在我的主控制器中,我定义了$ rootScope.items = [{id:1,..},{id:2,..},{id:3,..},..]和我的其他控制器我定义了$ scope.totVal = 0和items数组的观察器,当items数组更改时更新了totVal;
.controller('MainCtrl', ['$rootScope', '$scope', function($rootScope, $scope) {
// Are actually fetched from a service
$rootScope.items = [
{id: 1,..},
{id: 2,..},
..
];
}])
.controller('MyCtrl', ['$rootScope', '$scope', function($rootScope, $scope) {
$rootScope.updateTotVal = function() {
var totVal = 0;
// calculations are done here
// Is correct here when I console log after all calculations are complete
console.log(totVal);
$scope.totVal = totVal;
}
$scope.totVal = 0;
$rootScope.$watch('items', function() {
$rootScope.updateTotVal();
}, true);
}]);
我遇到的问题是totVal在视图中没有更新。当我控制台记录它在控制台中正确显示的值时,如果我将totVal div滚出视图并再次返回,它只会在视图中更新。看起来像是Chrome中的AngularJS错误,但在Google上找不到任何类似的情况。它在FireFox中运行良好。
如果我在ng-repeat之前移动totVal它可以工作,如果我删除了ng-repeat它可以工作(我宁愿不改变html的结构,因为它会有很多工作并且会使设计变得更糟)。我也尝试将totVal移动到根范围而没有任何成功。
只有绘画/渲染失败,Batarang和console.log总是给我更新的值。
以前有没有人遇到这个问题?
答案 0 :(得分:1)
我不知道这是否正是您所寻找的,因为我不知道您的用例。 但是,我实现了一个工作示例,请在此处查看codepen。
我重构了你的代码,删除了额外的控制器并在服务中封装了totVal
。此外,我使用controllerAs
语法使一切更清晰。
代码的问题在于totVal
是一个原语。因此,当您为其指定新值时,angular将无法更新引用。这就是为什么你应该在模型中总是有一个点!
看一下我的代码,你会认为totVal
为var totVal = {val : 0}
。我只是更新val
,保留引用并正确更新视图。
.service('totVal', function(){
var totVal = {val:0};
this.computeTotVal = function(){
//perform computations, I will just increment
totVal.val++;
}
this.getTotVal = function() { return totVal; }
})
另见article。
答案 1 :(得分:0)
我不确定这是否是罪魁祸首,但你绝对不应该使用$rootScope
。
正如文件所述:
$ rootScope存在,但它可以用于邪恶
见这里:https://docs.angularjs.org/misc/faq#-rootscope-exists-but-it-can-be-used-for-evil
如果没有必要,我会在没有它的情况下重写代码:
<div ng-controller="MainCtrl">
<div>Views and other stuff</div>
<div ng-controller="MyCtrl">
<!-- You also had an $root.items that didn't match any element here -->
<div ng-repeat="item in items track by $index">
{{item.id}}
</div>
<div>
Total value: {{totVal}}
</div>
</div>
</div>
在您的控制器中,您将绑定您的项目,如下所示:
.controller('MainCtrl', ['$scope', function($scope) {
// Are actually fetched from a service
$scope.items = [
{id: 1,..},
{id: 2,..},
..
];
}])
.controller('MyCtrl', ['$rootScope','$scope', function($rootScope, $scope) {
$scope.updateTotVal = function() {
var totVal = 0;
// calculations
console.log(totVal); // Is correct here
$scope.totVal = totVal;
}
$scope.totVal = 0;
// Here $rootScope makes sense
$rootScope.$watch('items', function() {
$scope.updateTotVal();
}, true);
}]);
修改强>
此外,每次实例化控制器时,都会设置$rootScope.totalVal = 0
,最终将其重置
也许这就是你没有看到更新的原因?
答案 2 :(得分:0)
问题出在Angular和Chrome上。如果我删除了在totVal输出之前的ng-repeat,那么它是否有效。如果我将totVal放在DOM结构中或ng-repeat之前,它也有效。 我认为它与绑定的数量和DOM的复杂性有关,许多嵌套的DIV以某种方式打破了绑定。我还注意到,如果我有很多嵌套的引导类,比如&#39; row&#39;和&#39; col-xs-12&#39;它也打破了绑定。所以它似乎与浏览器渲染/绘制视图有关(因为滚动totVal并返回到视图更新了值)。
我从中学到的主要内容是使用更智能的指令并尝试简化DOM结构,特别是如果你使用bootstrap。
原件:
<div ng-controller="MainCtrl">
<div>Views and other stuff</div>
<div ng-controller="MyCtrl">
<div ng-repeat="item in $root.items track by $index">
{{item.id}}
</div>
<div>
Total value: {{totVal}}
</div>
</div>
</div>
使其正常运行的不同更改:
<div ng-controller="MainCtrl">
<div>Views and other stuff</div>
<div ng-controller="MyCtrl">
<div>
Total value: {{totVal}}
</div>
</div>
</div>
<div ng-controller="MainCtrl">
<div>Views and other stuff</div>
<div ng-controller="MyCtrl">
<div ng-repeat="item in $root.items track by $index">
{{item.id}}
</div>
</div>
<div>
Total value: {{totVal}}
</div>
</div>
<div ng-controller="MainCtrl">
<div>Views and other stuff</div>
<div ng-controller="MyCtrl">
<div>
Total value: {{totVal}}
</div>
<div ng-repeat="item in $root.items track by $index">
{{item.id}}
</div>
</div>
</div>