Что такое "track by" в AngularJS и как это работает?

Я действительно не понимаю, как track by работает и что она делает.
Моя главная цель-использовать его с ng-repeat чтобы добавить некоторую точность.

3 ответов


используя track by для отслеживания строк и повторяющихся значений

нормально ng-repeat отслеживает каждый элемент по самому элементу. Для данного массива objs = [ 'one', 'one', 2, 'five', 'string', 'foo'], ng-repeat пытается отслеживать изменения по каждому obj на ng-repeat="obj in objs". Проблема в том, что у нас есть дубликаты значений, и angular выдаст ошибку. Один из способов решить эту проблему-угловое отслеживание объектов другими средствами. Для строк track by $index является хорошим решением, поскольку у вас действительно нет других средств для отслеживания строка.

track by & запуск дайджеста и ввод фокусов

вы намекаете на то, что вы несколько новичок в angular. Цикл дайджеста происходит, когда angular выполняет исчерпывающую проверку каждого наблюдаемого свойства, чтобы отразить любое изменение в представлении correspodant; часто во время дайджеста происходит, что ваш код изменяет другие наблюдаемые свойства, поэтому процедуру необходимо выполнить снова, пока angular не обнаружит больше изменений.

например: вы нажмите кнопку, чтобы обновить модель через ng-click, затем вы делаете что-то (я имею в виду, то, что вы написали в обратном вызове, чтобы выполнить, когда пользователь делает щелчок), затем угловой триггер дайджест цикла для обновления представления. Я не слишком четко объясняю это, поэтому вы должны исследовать дальше, если это не прояснило вещи.

Итак, вернемся к track by. Приведем пример:

  1. вызов службы для возврата массива объектов
  2. обновить объект в массиве и сохранить объект
  3. после сохранения службы, в зависимости от того, что возвращает API, вы можете:
    1. заменить весь объект или
    2. обновить значение существующего объекта
  4. отразить изменения в ng-repeat UI

как вы отслеживаете этот объект, определит, как пользовательский интерфейс отражает изменение.

один из самых раздражающих UXs, которые я испытал, это. Скажем, у вас есть стол объекты, каждая ячейка имеет вход, где вы хотите в строке редактировать свойства этих объектов. Я хочу изменить значение, то on-blur, сохраните этот объект при перемещении в следующую ячейку для редактирования во время ожидания ответа. Итак,это автосохранение. В зависимости от того, как вы настраиваете свой track by оператор, вы можете потерять текущий фокус (например, поле, которое вы в настоящее время редактируете), когда ответ будет записан обратно в массив объектов.


при добавлении track by вы в основном говорите angular генерировать один элемент DOM для каждого объекта данных в данной коллекции.

вы можете track by $index если ваш источник данных имеет повторяющиеся идентификаторы.

Если вам нужно повторить повторяющиеся элементы,вы можете заменить поведение отслеживания по умолчанию своим собственным, используя трек по выражению.

пример:

[{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

попробуйте использовать повторяющиеся значения в ng-repeat, вы получите сообщение об ошибке например:

ошибка: ngRepeat: обманывает дубликат ключа в повторителе

чтобы избежать такого рода проблем, вы должны использовать track by $index. Например:

<ul>
   <li ng-repeat="item in [1, 2, 3, 3] track by $index">
       {{ item }}
   </li>
</ul>

вот как вы получите $index во вложенных ng-repeat:

<div ng-repeat="row in matrix">
    <div ng-repeat="column in row">
      <span>outer: {{$parent.$index}} inner: {{$index}}</span>
    </div>
</div>

вот некоторые ресурсы, которые могут помочь вам:


вы должны использовать track by только если вам нужно пойти против поведения по умолчанию ng-repeat который должен удалить повторяющиеся элементы.
Вы можете отслеживать элементы с помощью свойства scope $index или указание пользовательской функции.

например:

<div ng-repeat="x in [42, 42, 43, 43] track by $index">
  {{x}}
</div>

отобразить все значения массива (42 отображается дважды).

для справки:https://docs.angularjs.org/api/ng/directive/ngRepeat