Циклы и повторители

Фреймворк Polymer предоставляет мощные средства для организации динамического отображения повторяющихся данных с помощью специальных шаблонов и привязок. Основным инструментом для работы с коллекциями является элемент <dom-repeat>, который позволяет создавать циклы по массивам данных и автоматически обновлять DOM при изменении данных.


Элемент <dom-repeat>

<dom-repeat> используется для генерации повторяющихся элементов на основе массива. Основные атрибуты:

  • items — массив данных, по которому выполняется итерация.
  • as — имя переменной для текущего элемента массива внутри шаблона.
  • index-as — имя переменной для текущего индекса элемента.
  • observe — массив свойств, за изменениями которых необходимо следить для обновления шаблона.

Пример базового использования:

<dom-module id="user-list">
  <template>
    <ul>
      <dom-repeat items="[[users]]" as="user" index-as="i">
        <template>
          <li>[[i]]: [[user.name]] ([[user.age]] лет)</li>
        </template>
      </dom-repeat>
    </ul>
  </template>

  <script>
    class UserList extends Polymer.Element {
      static get is() { return 'user-list'; }
      static get properties() {
        return {
          users: {
            type: Array,
            value: () => [
              {name: 'Иван', age: 30},
              {name: 'Мария', age: 25},
              {name: 'Пётр', age: 40}
            ]
          }
        };
      }
    }
    customElements.define(UserList.is, UserList);
  </script>
</dom-module>

В этом примере каждый объект массива users преобразуется в элемент списка <li>. Изменения в массиве автоматически отображаются в DOM.


Двусторонняя привязка данных

<dom-repeat> поддерживает двустороннюю привязку, что позволяет изменять данные в шаблоне и автоматически синхронизировать их с моделью:

<dom-repeat items="[[users]]" as="user">
  <template>
    <input value="{{user.name::input}}">
  </template>
</dom-repeat>

Атрибут {{user.name::input}} обеспечивает реакцию на событие input, мгновенно обновляя массив users.


Фильтрация и сортировка

<dom-repeat> предоставляет встроенные методы для фильтрации и сортировки:

  • filter — функция фильтрации элементов.
  • sort — функция сортировки элементов.

Пример сортировки и фильтрации:

<dom-repeat items="[[users]]" as="user" filter="filterAdults" sort="sortByName">
  <template>
    <div>[[user.name]] ([[user.age]])</div>
  </template>
</dom-repeat>

<script>
  class UserList extends Polymer.Element {
    static get is() { return 'user-list'; }
    static get properties() {
      return {
        users: {
          type: Array,
          value: () => [
            {name: 'Иван', age: 30},
            {name: 'Мария', age: 25},
            {name: 'Пётр', age: 40}
          ]
        }
      };
    }

    filterAdults(user) {
      return user.age >= 18;
    }

    sortByName(a, b) {
      return a.name.localeCompare(b.name);
    }
  }
  customElements.define(UserList.is, UserList);
</script>

Элементы массива сначала фильтруются функцией filterAdults, затем сортируются по алфавиту.


Динамическое обновление данных

Polymer позволяет динамически изменять массивы с помощью методов push, pop, splice, shift, unshift, set и автоматически обновлять <dom-repeat>:

this.push('users', {name: 'Алексей', age: 28});
this.splice('users', 1, 1, {name: 'Светлана', age: 32});

Каждое изменение корректно отражается в DOM без необходимости ручного рендеринга.


Локальные переменные шаблона

Внутри <dom-repeat> доступны переменные:

  • item или имя, указанное в as — текущий элемент массива.
  • index или имя, указанное в index-as — индекс элемента.
  • odd и even — булевы значения для нечётных и чётных элементов, полезные для стилизации.
<dom-repeat items="[[users]]" as="user" index-as="i">
  <template>
    <div class$="[[oddOrEven(i)]]">
      [[user.name]]
    </div>
  </template>
</dom-repeat>

<script>
  oddOrEven(index) {
    return index % 2 === 0 ? 'even' : 'odd';
  }
</script>

Вложенные циклы

Поддерживаются вложенные <dom-repeat> для работы с массивами массивов:

<dom-repeat items="[[users]]" as="user">
  <template>
    <h3>[[user.name]]</h3>
    <ul>
      <dom-repeat items="[[user.friends]]" as="friend">
        <template>
          <li>[[friend]]</li>
        </template>
      </dom-repeat>
    </ul>
  </template>
</dom-repeat>

Такой подход позволяет строить сложные структуры интерфейса на основе многоуровневых данных.


Производительность и оптимизация

Для больших массивов рекомендуется использовать restamp и observe:

  • restamp="true" полностью пересоздаёт элементы при изменении данных, что может быть полезно для радикальных обновлений.
  • observe отслеживает конкретные свойства, минимизируя лишние ререндеры.

События <dom-repeat>

Элемент <dom-repeat> генерирует события, которые помогают отслеживать изменения:

  • dom-change — вызывается при изменении элементов.
  • dom-item-added и dom-item-removed — отслеживают добавление и удаление элементов.

Пример подписки на событие:

this.$.repeat.addEventListener('dom-change', () => {
  console.log('Список обновлён');
});

Резюме ключевых возможностей

  • Генерация списков через <dom-repeat> на основе массива данных.
  • Поддержка двусторонней привязки.
  • Фильтрация и сортировка элементов через функции.
  • Динамическое обновление массивов с автоматическим рендером.
  • Использование локальных переменных item, index, odd, even.
  • Вложенные циклы для сложных структур.
  • Контроль производительности через observe и restamp.
  • События для отслеживания изменений в DOM.