Фильтр списка тренировок на чистом JavaScript: разбор интерфейса

Простой интерфейс фильтра списка тренировок на ноутбуке

Фильтр списка можно построить без фреймворка, если разделить исходные данные, условие отбора и вывод. В примере пользователь выбирает тип тренировки, а список и число результатов обновляются вместе. Исходный массив не меняется, поэтому возврат к пункту «Все» не требует повторной загрузки.

Готовая страница

index.html

<!doctype html>
<html lang="ru"><meta charset="utf-8"><title>Фильтр тренировок</title>
<label for="type">Тип</label>
<select id="type"><option value="all">Все</option>
<option value="run">Бег</option><option value="walk">Ходьба</option></select>
<p id="count" aria-live="polite"></p><ul id="list"></ul>
<script>
const sessions = [
  { title: 'Лёгкий бег', type: 'run' },
  { title: 'Прогулка в парке', type: 'walk' },
  { title: 'Бег по стадиону', type: 'run' }
];
const select = document.querySelector('#type');
const list = document.querySelector('#list');
function filterSessions(items, type) {
  return items.filter(item => type === 'all' || item.type === type);
}
function render() {
  const found = filterSessions(sessions, select.value);
  const nodes = found.map(item => {
    const li = document.createElement('li');
    li.textContent = item.title;
    return li;
  });
  list.replaceChildren(...nodes);
  document.querySelector('#count').textContent = `Найдено: ${found.length}`;
}
select.addEventListener('change', render);
render();
</script></html>

Сохраните страницу как index.html и откройте в браузере. Сначала видны три пункта, при выборе «Бег» — два, при «Ходьба» — один. select уже поддерживает стандартное управление клавиатурой. Подпись связана с ним через for и id; отдельная область сообщает число результатов, не перемещая фокус.

Три части фильтра
Что сравнить На что смотреть Что сделать
sessions Полный набор данных Не перезаписывать отфильтрованным результатом
filterSessions Только отбор Можно тестировать без DOM
render Создание узлов и счётчик Обновлять из одного результата

Почему вывод создаётся узлами

Название помещается в textContent, поэтому текст не интерпретируется как разметка. Это особенно важно, если в будущем данные придут от пользователя. replaceChildren заменяет прежние элементы списка; повторный render не накапливает копии. Для большого набора потребуется другая оценка производительности, но добавлять виртуализацию к трём строкам незачем.

  • Вернуть выбор на «Все» и убедиться, что элементы не потеряны.
  • Добавить пустую категорию и проверить нулевой счётчик.
  • Проверить выбор только клавиатурой.
  • Проверить название со знаками угловых скобок как обычный текст.

Вопросы и ответы

Нужен ли обработчик каждому пункту?

Нет. Изменение фильтра приходит от одного select, после чего строится результат.

Почему не скрывать готовые строки?

Это тоже возможный подход. Здесь массив данных отделён от вывода, поэтому отбор проще проверить отдельно.

Куда добавить длительность?

В данные и создание элемента. Не смешивайте её с условием типа, пока не появился соответствующий фильтр.

Будет ли это искать на сервере?

Нет. Пример работает с локальным массивом в памяти страницы. Серверный поиск требует другого контракта и состояний загрузки.

Источники: developer.mozilla.org.

Похожие записи