我有一个简单的Angularjs应用程序,其控制器包含一个名为id
的字符串作用域列表:
angular.module('app', [])
.controller('appCtrl', ['$scope', '$timeout',
function($scope, $timeout) {
$scope.ids = ['id1', 'id2'];
}]);
在html partial中,ngrepeat迭代id并将此id添加到div列表中:
<div ng-app="app">
<div ng-controller="appCtrl">
<div ng-repeat="id in ids" ng-attr-id="{{id}}">
div-{{id}}
</div>
</div>
</div>
只有当它包含在$ timeout中时,才能在控制器中使用angular.element选择这些div:
$timeout(function(){
console.log('with timeout, element found');
console.log(angular.element('#'+$scope.ids[0]));
});
console.log('no timeout, element not found');
console.log(angular.element('#'+$scope.ids[0]));
以下是一个工作示例:https://codepen.io/neptune01/pen/zjqGzO
究竟是什么导致了这种异步流程?为什么我需要超时来选择元素?
我试图在可能的情况下摆脱超时。有没有更好的方法来进行元素选择,最终没有超时?
答案 0 :(得分:2)
正如我所听到的那样,AngularJs存在问题。控制器编码,在DOM完成之前执行,因此在没有$timeout
的情况下,没有要选择的标识'#'+$scope.ids[0]
。您必须使用$timeout
来选择和使用它。
有关更多信息,请搜索并阅读digest cycle of angularjs
。
答案 1 :(得分:1)
@ Saeed.At已指出正确的方向。
它与AngularJS摘要周期有关。 ng-repeat,ng-include和其他几个指令以及它们的渲染在下面的摘要周期中排队并呈现。例如,
现在你已经看到尝试在开始时直接访问ng-repeat项目不会起作用,因为它们只会在一个周期后再渲染。
$ timeout基本上是一样的。如果您没有提供超时参数,它将在下一个摘要周期后排队。因此链条看起来像这样
同样重要的是要注意,如果你的ng-repeat包含其他ng-includes或某些指令,他们也会自行排队,所以可能是单个$ timeout不够。对于这种情况,您必须采取不同的方法