Угловое ng-repeat вызывает мерцание

18

Я показываю список миниатюр с этим кодом:

<div class ="channel" ng-repeat ="channel in UIModel.channels" ng-class ="{evenchannel: ($index % 2) == 0, oddchannel: ($index % 2) == 1}">
            <img class="channel-img" ng-src ="data/channels/{{$index + 1}}/thumb"/>
</div>

В контроллере у меня есть запрос ajax, который захватывает новые уменьшенные изображения. Таким образом, Angular обновляет изображения, но вызывает мерцание. Есть ли способ удвоить буфер или не удалить список в процессе обновления DOM?

    
задан tyuo9980 10.06.2014 в 17:29
источник

5 ответов

30

Чтобы согласиться с ответом @ cexbrayat, если у вас нет идентификаторов, вы можете просто связать его и track by $index . Это внутренняя итерация # во время ng-repeat.

<div ng-repeat="channel in UIModel.channels track by $index"></div>
    
ответ дан Mark Pieszak - DevHelp.Online 10.06.2014 в 17:50
источник
  • Старый ответ, но работает для меня даже сегодня. Как «отслеживать по индексу» решает проблески? –  codemax 23.09.2016 в 09:28
  • Он использует внутренний хэш вместо создания «на лету», что заставляет его визуализировать медленнее, поэтому мерцание :) @codemax –  Mark Pieszak - DevHelp.Online 25.09.2016 в 02:25
  • Приятно, спасибо за ваш ответ :) –  codemax 27.09.2016 в 08:21
  • Работал для меня. Но кешированные страницы загружаются медленно. –  Naveen Kumar V 21.05.2018 в 15:21
11

Вы можете использовать track by в своем ng-repeat с уникальным идентификатором. Если я полагаю, что ваш объект канала имеет идентификатор, вы можете сделать:

<div class ="channel" ng-repeat="channel in UIModel.channels track by channel.id"></div>

Отслеживание позволяет избежать полного удаления DOM и рекреации при каждом обновлении, поскольку Angular сможет отслеживать, является ли элемент тем же, что и ранее, и сохранит элемент DOM.

    
ответ дан cexbrayat 10.06.2014 в 17:40
источник
  • Я использовал реализацию $ index, но теперь моя миниатюра не обновляется вообще. У меня есть другое свойство, которое отображает время и обновления. –  tyuo9980 10.06.2014 в 20:36
3

Сначала попробуйте ответы от @Mark Pieszak и @cexbrayat, однако, если вы используете ngAnimate в своем приложении, они могут не полностью решить вашу проблему.

В дополнение к:

<div class="channel" ng-repeat="channel in UIModel.channels track by channel.id"></div>

Мне нужно было добавить следующий CSS, чтобы отключить анимацию для этого ng-repeat :

.channel .ng-leave, .channel .ng-leave-active {
    display: none !important;
}

.channel .ng-move, .channel .ng-move-active {
    display: none !important;
}

Это гарантирует, что после начала анимации элемент сразу будет скрыт. Альтернативы - фактически использовать анимацию или отключить анимацию элемента в коде с $animate.enabled('div.channel', false); .

    
ответ дан sflogen 20.07.2017 в 20:07
источник
0

У меня была такая же проблема, используя трек по $ index, наконец, разрешил проблему для меня. Сначала я не думал, что это так, потому что я использовал его непосредственно в тегах изображений, где был еще один ng-repeat. Как только я положил его в родительский div (также) на ng-repeat, он сработал:

<div ng-repeat="item in blah track by $index">
   <!-- stuff -->
   <!-- later in this div: -->
   <img data-ng-repeat="dict in item.blah track by $index" class="smallPics ng-cloak" src="{[dict.path]}"></img>

   <!-- and the rest is blah-istory -->
    
ответ дан user2738183 23.06.2015 в 00:18
источник
0

Как примечание:

Если использование track by $index не обновляет DOM с новыми значениями,
рассмотрите возможность использования track by 'the properties you expect to change' , просто будьте осторожны, чтобы избежать ошибок ngDupe

например:

<div ng-repeat="channel in UIModel.channels track by customExp(channel)">

. , .

$scope.customExp = function(chan) {
    return chan.id+chan.thumbnail_url; // this has to ensure uniqueness
}

или

<div ng-repeat="channel in UIModel.channels track by channel.id+channel.thubnail_url">
    
ответ дан koox00 16.12.2016 в 15:32
источник