我有一个有角度的应用程序,如:
angular.module('ngStyleApp', [])
.controller('testCtrl', function($scope) {
$scope.list = [1,2,3];
$scope.getStyles = function(index) {
console.log('getting styles for index ' + index);
return {
color: 'red'
};
};
});
带有相应的标记:
<div ng-app="ngStyleApp">
<ul ng-controller="testCtrl">
<li ng-repeat="value in list" ng-style="getStyles($index)">
{{value}}
</li>
</ul>
</div>
可见输出是三个红色列表项,如预期的那样。但该语句总共被记录到控制台6次,这意味着视图呈现两次:
getting styles for index 0
getting styles for index 1
getting styles for index 2
getting styles for index 0
getting styles for index 1
getting styles for index 2
为什么吗
答案 0 :(得分:6)
Angular $digest
周期至少两次评估ngStyle属性 - 一次获取值,一次检查是否已更改。它实际上一直在迭代,直到值结算,因此可能会多次检查该值。
这是一张图片来说明这一点:
这是一篇很好的博客文章,说明了这一点: angular digest blog
实际上,请试试StackOverflow中的这句话,说得很清楚:
当评估观察到的函数时(在$ digest期间),如果它们中的任何一个已经从之前的$摘要发生了变化,那么Angular知道这种变化可能会波及其他观察函数(可能更改的变量用于另一个观察函数)。因此,每个手表都会被重新评估(也称为脏处理),直到所有手表都没有变化。因此,通常情况下,每次摘要会看到2次调用观看函数的次数,有时甚至更多(通过它的10次循环最多10次放弃并报告错误,表示无法稳定)。
(参考here)
答案 1 :(得分:1)
这是ngStyle
指令的代码:
var ngStyleDirective = ngDirective(function(scope, element, attr) {
scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) { element.css(style, '');});
}
if (newStyles) element.css(newStyles);
}, true);
});
请注意,scope.$watch
有一个attr.ngStyle
,该手表会触发两次。
例如,如果您尝试使用ngInit
执行相同的操作,您会注意到该函数只被调用一次。现在,让我们看一下ngInit
指令的代码,它看起来像这样:
var ngInitDirective = ngDirective({
priority: 450,
compile: function() {
return {
pre: function(scope, element, attrs) {
scope.$eval(attrs.ngInit);
}
};
}
});
请注意,此指令中没有watch
。