我是 Angular(1.x) 的完全初学者,我一直在尝试将其整合到我当前正在开发的应用程序中。
它基本上通过 ajax(多个嵌套数组)接收整个用户数据,然后使用嵌套的 ng-repeat 指令继续渲染它们。在最里面的重复中,我运行一个函数,该函数根据当前日期返回数据。
<div ng-repeat="i in rootArray">
<div ng-repeat="h in i.array1">
<div ng-repeat="j in h.array2">
<span>{{dateBasedFunction(j.data)}}</span>
</div>
</div>
</div>
函数中的数据随着时间的推移而变化(即使输入保持不变),我希望它重新运行以反射(reflect)这些变化,而无需再次渲染整个结构。
这可能吗?我不确定我是否遵循了最佳框架的实践,也许有更好的方法?
谢谢!
最佳答案
背景
ng-repeats 不会造成任何问题。我们需要关注interpolation expression :{{dateBasedFunction(j.data)}}
Angular 正在创建一个 watcher在 digest 的每次迭代中对表达式 dateBasedFunction(j.data)
进行脏检查循环。如果自上次摘要以来结果值已更改,则 DOM 将使用新值进行更新。
问题是,您的代码中没有任何内容触发 Angular 摘要周期。
工作示例
在这里,我们可以通过用户交互手动触发摘要来查看您的情况:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', MyCtrl]);
function MyCtrl($scope) {
$scope.rootArray = [{
"array1": [{
"array2": [{
"data": "hello"
}, {
"data": "world"
}]
}]
}];
//Dummy $watch alerts whenever digest is called
$scope.$watch(function() {
console.log('Digest called');
});
$scope.dateBasedFunction = function(x) {
var d = new Date();
return x + ' (' + d.getMinutes() + ":" + d.getSeconds() + ")";
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<button ng-click="">ng-click calls digest()</button>
<div ng-repeat="i in rootArray">
<div ng-repeat="h in i.array1">
<div ng-repeat="j in h.array2">
<span>{{dateBasedFunction(j.data)}}</span>
</div>
</div>
</div>
</div>
</div>
每次单击按钮时,ng-click
都会触发 Angular 摘要。这会重新评估dateBasedFunction
。由于值已更改,因此 DOM 会重新绘制。
但是,我假设您不想依赖 ng-click
来保持 DOM 更新。您希望 DOM 定期更新,因为它会根据当前日期/时间而变化。
可能的解决方案
- 确定适合您需求的频率,并定期强制执行摘要周期:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', MyCtrl]);
function MyCtrl($scope) {
$scope.rootArray = [{
"array1": [{
"array2": [{
"data": "hello"
}, {
"data": "world"
}]
}]
}];
//Dummy $watch alerts whenever digest is called
$scope.$watch(function() {
console.log('Digest called');
});
$scope.dateBasedFunction = function(x) {
var d = new Date();
return x + ' (' + d.getMinutes() + ":" + d.getSeconds() + ")";
}
//Call $scope.$apply() every second.
setInterval(function() {
//$scope.$apply() triggers a digest cycle
$scope.$apply();
}, 1000);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="i in rootArray">
<div ng-repeat="h in i.array1">
<div ng-repeat="j in h.array2">
<span>{{dateBasedFunction(j.data)}}</span>
</div>
</div>
</div>
</div>
</div>
如果您知道更新的频率,您可以考虑编写一个在正确时间直接更新 DOM 的指令,而无需在整个范围内调用
apply()
。这会更高效,但需要更多的开发工作。这正是angular-moment与他们的
am-time-ago
directive 一起做。该指令具有类似的目标:更新响应当前日期/时间而变化的数据。使用 Angular 观察模型的任何更改,但在 Angular 之外处理基于日期/时间的更改:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', MyCtrl]);
function MyCtrl($scope) {
$scope.rootArray = [{
"array1": [{
"array2": [{
"data": "hello"
}, {
"data": "world"
}]
}]
}];
//Dummy $watch alerts whenever digest is called
$scope.$watch(function() {
console.log('Digest called');
});
}
function dateBasedFunction(x) {
var d = new Date();
return x + ' (' + d.getMinutes() + ":" + d.getSeconds() + ")";
}
setInterval(function() {
$('[data-date-based-value]').each(function() {
this.textContent = dateBasedFunction(this.dataset['dateBasedValue']);
});
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="i in rootArray">
<div ng-repeat="h in i.array1">
<div ng-repeat="j in h.array2">
<!--Set a data-date-based-value attribute-->
<!--Angular will keep the attribute value updated-->
<!--But the element's text will be updated via jQuery-->
<span ng-attr-data-date-based-value="{{j.data}}"></span>
</div>
</div>
</div>
</div>
</div>
请注意,此解决方案直接更新 DOM,无需运行额外的摘要周期。
This article如果您有兴趣了解有关 Angular 的更多信息,它很好地解释了摘要周期。
关于javascript - 强制刷新 Angular 中的嵌套函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45322961/