Краткий ответ : действительно ли вам нужна такая функция или можно использовать собственность? http://jsfiddle.net/awnqm/1/
Длинный ответ
Для простоты опишу только ваш случай - ngRepeat для массива объектов. Также я опущу некоторые детали.
AngularJS использует грязную проверку для обнаружения изменений. При запуске приложения оно работает $digest
для $rootScope
. $digest
выполнит обход в глубину для иерархии области видимости . У всех прицелов есть список часов. Каждые часы имеют последнее значение (изначально initWatchVal
). Для каждой области видимости для всех часов $digest
он запускается, получает текущее значение ( watch.get(scope)
) и сравнивает его с watch.last
. Если текущее значение не равно watch.last
(всегда для первого сравнения), $digest
устанавливается dirty
в true
. Когда все области видимости обрабатываются, if dirty == true
$digest
начинает еще один обход в глубину из $rootScope
. $digest
заканчивается, когда dirty == false или количество обходов == 10. В последнем случае выдается ошибка «Достигнуто 10 итераций $ digest ()». будет зарегистрирован.
Теперь о ngRepeat
. Для каждого watch.get
вызова он сохраняет объекты из коллекции (возвращающее значение getEntities
) с дополнительной информацией в кеше ( HashQueueMap
by hashKey
). При каждом watch.get
вызове ngRepeat
пытается получить объект hashKey
из кеша. Если он не существует в кеше, ngRepeat
сохраняет его в кеше, создает новую область видимости, помещает в нее объект, создает элемент DOM и т . Д.
Теперь о hashKey
. Обычно hashKey
это уникальный номер, генерируемый nextUid()
. Но это может быть функция . hashKey
после создания сохраняется в объекте для использования в будущем.
Почему ваш пример генерирует ошибку : функция getEntities()
всегда возвращает массив с новым объектом. У этого объекта нет hashKey
и не существует в ngRepeat
кеше. Таким образом, ngRepeat
каждый watch.get
генерирует для него новые возможности с новыми часами {{entity.id}}
. Это смотрела на первых watch.get
порах watch.last == initWatchVal
. Итак watch.get() != watch.last
. Итак, $digest
начинается новый траверс. Таким образом ngRepeat
создается новая сфера применения новых часов. Итак ... после 10 ходов вы получаете ошибку.
Как это исправить
- Не создавайте новые объекты при каждом
getEntities()
вызове.
- Если вам нужно создать новые объекты, вы можете добавить
hashKey
для них метод. Примеры см. В этой теме .
Надеюсь, люди, знающие внутренности AngularJS, поправят меня, если я в чем-то ошибаюсь.
Do not create new objects on every getEntities() call.
это можно легко исправить следующим образом:<div ng-repeat="entity in entities = (entities || getEntities())">
getEntities()
всегда возвращает один и тот же массив, если массив когда-либо изменится, вы не получите его вng-repeat
Инициализировать массив вне повтора
источник
getEntities()
в жизненном цикле программы возвращается что-то другое. Скажем, например, чтоgetEntities()
триггер$http.get
. Когда get, наконец, разрешится (вы сделали вызов AJAX),entities
он уже будет инициализирован.The only appropriate use of ngInit is for aliasing special properties of ngRepeat. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
Об этом сообщили здесь и получили такой ответ:
Вы можете увидеть, как это поведение исчезнет, если вы переместите массив за пределы главного контроллера:
потому что теперь он каждый раз возвращает один и тот же объект. Возможно, вам придется перестроить вашу модель, чтобы использовать свойство в области вместо функции:
источник
На основе комментария @przno
Кстати, второе решение, которое предлагает @Artem Andreev, не работает в Angular 1.1.4 и выше, а первое не решает проблему. Так что, боюсь, пока это менее острое решение без недостатков в функциональности.
источник
Item.id
это то, что должно б. Спасибо