[angularjs] ng-repeat를 사용하여 함수에서 반환 한 항목을 반복하는 방법은 무엇입니까?

반복적으로 div를 만들고 싶습니다. 항목은 함수에서 반환하는 개체입니다. 그러나 다음 코드는 오류를보고합니다. 10 $ digest () 반복에 도달했습니다. 중단! jsfiddle은 여기에 있습니다 : http://jsfiddle.net/BraveOstrich/awnqm/

<body ng-app>
  <div ng-repeat="entity in getEntities()">
    Hello {{entity.id}}!
  </div>
</body>



답변

짧은 대답 : 정말로 그러한 기능이 필요합니까 아니면 속성을 사용할 수 있습니까? http://jsfiddle.net/awnqm/1/

긴 대답

단순화를 위해 객체 배열에 대한 ngRepeat의 경우 만 설명합니다. 또한 세부 사항은 생략하겠습니다.

AngularJS는 변경 사항을 감지하기 위해 더티 검사 를 사용합니다 . 응용 프로그램이 시작되면 그것은 실행 $digest을 위해 $rootScope. 범위의 계층에$digest 대해 깊이 우선 순회를 수행 합니다 . 모든 범위에는 시계 목록이 있습니다. 각 시계에는 마지막 값이 있습니다 (처음에는 initWatchVal). 모든 시계에 대한 각 범위에 대해 $digest실행하고 현재 값 ( watch.get(scope))을 가져 와서 watch.last. 현재 값이 watch.last(항상 첫 번째 비교를 위해) 같지 않으면로 $digest설정 dirty됩니다 true. 경우 모든 범위를 처리 할 때 dirty == true $digest의 또 다른 깊이 우선 탐색을 시작합니다 $rootScope. $digestdirty == false 또는 순회 횟수 == 10 일 때 종료됩니다. 후자의 경우 “10 $ digest () 반복에 도달했습니다.”오류가 발생합니다. 기록됩니다.

이제 ngRepeat. 각 watch.get호출에 대해 getEntities캐시 ( HashQueueMapby hashKey) 에 추가 정보와 함께 컬렉션 (값 반환)의 개체를 저장합니다 . 모든 watch.get호출 ngRepeat에 대해 hashKey캐시에서 객체를 가져 오려고 합니다. 캐시에 존재하지 않는 경우 캐시에 ngRepeat저장하고, 새 범위를 생성하고, 객체를 배치하고, DOM 요소를 생성하는 등의 작업을 수행 합니다.

이제 hashKey. 일반적으로에서 hashKey생성 한 고유 번호 nextUid()입니다. 그러나 그것은 기능 일 수 있습니다 . hashKey나중에 사용하기 위해 생성 후 객체에 저장됩니다.

예제에서 오류가 발생하는 이유 : 함수는 getEntities()항상 새 객체로 배열을 반환합니다. 이 개체는 캐시에 hashKey없으며 존재하지 않습니다 ngRepeat. 따라서 ngRepeat각각에 watch.get대한 새 시계를 사용하여 새 범위를 생성합니다 {{entity.id}}. 이 시계는 처음 watch.getwatch.last == initWatchVal. 그래서 watch.get() != watch.last. 그래서 $digest새로운 횡단을 시작합니다. 그래서 ngRepeat새로운 시계로 새로운 범위를 만듭니다. 그래서 … 10 번의 트래버스 후에는 오류가 발생합니다.

고칠 수있는 방법

  1. 모든 getEntities()호출 에서 새 개체를 만들지 마십시오 .
  2. 새 개체를 만들어야하는 경우 hashKey메서드를 추가 할 수 있습니다 . 예제는 이 주제 를 참조하십시오 .

AngularJS 내부를 아는 사람들이 내가 뭔가 잘못되면 나를 바로 잡기를 바랍니다.


답변

반복 외부에서 배열 초기화

<body ng-app>
   <div ng-init="entities = getEntities()">
       <div ng-repeat="entity in entities">
           Hello {{entity.id}}!
       </div>
   </div>
</body>


답변

여기에 보고되었으며 다음 과 같은 응답을 받았습니다.

getter는 멱 등성이 아니며 모델을 변경합니다 (호출 될 때마다 새 배열을 생성 함). 이것은 모델이 결국 안정화되기를 바라면서 angular가 계속 호출하도록 강요하지만 결코 그렇게하지 않습니다. angular는 포기하고 예외를 던집니다.

게터가 반환하는 값은 동일하지만 동일하지는 않으며 그게 문제입니다.

메인 컨트롤러 외부로 어레이를 이동하면이 동작이 사라지는 것을 볼 수 있습니다.

var array = [{id:'angularjs'}];
function Main($scope) {
    $scope.getEntities = function(){return array;};
};

이제 매번 동일한 객체를 반환하기 때문입니다. 함수 대신 범위의 속성을 사용하려면 모델을 다시 설계해야 할 수 있습니다.

컨트롤러 메서드의 결과를 속성에 할당하고 이에 대해 ng : repeat를 수행하여 문제를 해결했습니다.


답변

@przno 주석을 기반으로

<body ng-app>
  <div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()">
    Hello {{item.id}}!
  </div>
</body>

BTW 두 번째 솔루션 @Artem Andreev는 Angular 1.1.4 이상에서 작동하지 않는 반면 첫 번째 솔루션은 문제를 해결하지 않는다고 제안합니다. 그래서 지금은 이것이 기능상의 단점이없는 덜 뾰족한 솔루션입니다.


답변