Перейти к содержанию

Примерные вопросы для зачета с оценкой по дисциплине «Основы разработки веб-сервисов»

Структура оценивания

  • Вопрос 1-го типа — 20 баллов
  • Вопрос 2-го типа — 20 баллов
  • Вопрос 3-го типа — 60 баллов

Задание 1 (вопросы 1-го типа, 20 баллов)

Ответить на теоретические вопросы, дать определения, классификации, перечисления.

  1. В чём ключевое отличие HTML5 от ранних версий HTML (2.0 / 4.01)?
  2. Какова роль W3C в развитии HTML?
  3. Чем HTML отличается от XML и XHTML?
  4. Что такое DOM и почему его называют объектной моделью документа?
  5. Как браузер интерпретирует HTML-документ?
  6. Для чего используется <!DOCTYPE html>?
  7. Из каких обязательных частей состоит базовый HTML-документ?
  8. В чём различие блочных и строчных элементов?
  9. Что такое семантические элементы HTML5 и зачем они нужны?
  10. В чём различие <div> и семантических элементов (<section>, <article>)?
  11. Чем отличаются методы GET и POST?
  12. Для чего используются атрибуты required, pattern, minlength, maxlength?
  13. Чем отличаются checkbox и radio?
  14. Какую роль играют <thead>, <tbody>, <tfoot>?
  15. Что такое атрибуты rowspan и colspan?
  16. Что такое каскадность в CSS?
  17. Что такое специфичность селекторов?
  18. Чем отличается Flexbox от Grid?
  19. Что входит в Box Model?
  20. Зачем используется box-sizing: border-box?
  21. Что делают transition и animation?
  22. В чём отличие псевдоклассов и псевдоэлементов?
  23. Какова роль JavaScript в архитектуре Web-приложения?
  24. В чём отличие let и const?
  25. Какие существуют примитивные типы данных в JavaScript?
  26. Чем отличается map() от forEach()?
  27. Что делает метод reduce()?
  28. Чем querySelector отличается от getElementById?
  29. Что такое асинхронность в JavaScript и зачем она нужна?
  30. Почему нельзя доверять данным, полученным от пользователя?

Задание 2 (вопросы 2-го типа, 20 баллов)

Развёрнутые аналитические вопросы с пояснениями и примерами.

  1. Почему переход от <div>-верстки к семантическим тегам улучшает SEO и доступность?
  2. Что произойдёт, если не указать кодировку UTF-8?
  3. Почему важно соблюдать правильную иерархию заголовков (h1–h6)?
  4. В каких случаях таблица должна использоваться только для табличных данных, а не для верстки?
  5. Почему <img> обязан иметь атрибут alt?
  6. Чем опасно использование target="_blank" без rel="noopener"?
  7. Почему структура HTML-документа важнее его визуального оформления?
  8. Как HTML участвует в формировании Render Tree браузера?
  9. Почему селектор #id имеет более высокий приоритет, чем .class?
  10. Что произойдёт, если задать ширину 300px без border-box и добавить padding: 20px?
  11. Почему чрезмерное использование !important разрушает архитектуру CSS?
  12. В каких случаях Flexbox менее удобен, чем Grid?
  13. Почему подход Mobile-first считается предпочтительным?
  14. Как Media Queries влияют на производительность страницы?
  15. Почему inline-стили считаются плохой практикой?
  16. Чем опасны слишком сложные CSS-селекторы (например, div > ul > li > span)?
  17. Почему неправильное использование position: absolute может нарушить layout?
  18. Как некорректный z-index создаёт проблемы перекрытия элементов?
  19. Почему метод sort() может неожиданно изменить исходный массив?
  20. В чём разница между мутацией объекта и созданием его копии?
  21. Почему необходимо использовать event.preventDefault() при работе с формами?
  22. Что произойдёт, если не проверить res.ok при использовании fetch()?
  23. Чем опасно использование innerHTML с пользовательскими данными?
  24. Почему функции валидации рекомендуется делать “чистыми”?
  25. Как делегирование событий улучшает производительность интерфейса?
  26. Почему важно разделять UI-слой и бизнес-логику в JavaScript?
  27. Что произойдёт, если не обернуть await в try/catch?
  28. Почему нельзя хранить чувствительные данные только на клиентской стороне?
  29. Чем отличается фильтрация массива от поиска элемента?
  30. Почему клиентская валидация не заменяет серверную проверку данных?

Задание 3 (вопросы 3-го типа, 60 баллов)

Практико-ориентированные задания, требующие анализа, проектирования и разработки кода.


Задание 1.

Кейс

В web-приложении отображается список товаров. Пользователь должен перейти к карточке товара по клику на ссылку (или кнопку), при этом навигация может быть как внутренней (якоря), так и через относительные/абсолютные пути. Важно обеспечить корректность ссылок и безопасность при открытии внешних ресурсов.

Задание

Разработайте фрагмент HTML + JS, который:

  1. содержит список ссылок на товары (минимум 5), где часть ссылок — относительные, часть — абсолютные, часть — якоря (#id);
  2. добавляет обработчик клика по всем ссылкам через делегирование событий;
  3. определяет тип ссылки (anchor / relative / absolute);
  4. для абсолютных ссылок автоматически добавляет target="_blank" и rel="noopener noreferrer";
  5. для якорных ссылок выполняет плавную прокрутку к секции.

Результат

  • в консоль выводится тип ссылки и её значение;
  • внешние ссылки открываются безопасно;
  • якоря корректно прокручивают страницу.

Задание 2.

Кейс

На странице присутствует блок <picture> для адаптивной выдачи изображений. В зависимости от ширины экрана браузер должен выбирать подходящий источник. Дополнительно требуется контролировать наличие alt и оптимизацию формата.

Задание

Разработайте HTML + JS, который:

  1. создаёт компонент изображения через <picture> + <source> + <img> (минимум 2 source под разные условия);
  2. задаёт корректный alt и размеры (для предотвращения layout shift);
  3. на JS проверяет, что img.alt не пустой;
  4. если alt пустой — выводит предупреждение и подставляет значение по умолчанию;
  5. выводит в консоль текущий выбранный currentSrc.

Результат

  • изображение корректно отображается на разных ширинах;
  • alt гарантированно заполнен;
  • в консоль выводится фактический источник currentSrc.

Задание 3.

Кейс

Для SEO и корректного отображения в поиске необходимо автоматически контролировать наличие ключевых метатегов (title, description, charset, viewport). В проекте часть страниц может быть собрана из шаблонов и метатеги иногда пропадают.

Задание

Разработайте скрипт на JavaScript, который:

  1. проверяет наличие <meta charset>, <meta name="viewport">, <title>, <meta name="description">;
  2. если чего-то не хватает — добавляет недостающий тег в <head>;
  3. для description устанавливает длину не более 160 символов (обрезка с );
  4. логирует список добавленных/исправленных тегов;
  5. корректно работает при повторном запуске (не дублирует теги).

Результат

  • DOM в <head> содержит полный набор базовых метаданных;
  • в консоль выводится отчёт: что было добавлено/исправлено.

Задание 4.

Кейс

В форме регистрации часть полей должна валидироваться встроенными средствами HTML (required, minlength, pattern, type=email), а часть — дополнительной логикой JS (например, запрет пробелов в начале/конце, проверка сложности пароля).

Задание

Разработайте HTML-форму + JS, которая:

  1. включает поля name, email, password, confirmPassword;
  2. использует HTML-валидацию: required, minlength, type="email", pattern (для имени/пароля);
  3. в обработчике submit отменяет отправку и собирает ошибки;
  4. дополнительно проверяет:

  5. trim для name/email;

  6. совпадение паролей;
  7. наличие цифры в пароле;
  8. выводит ошибки списком на страницу (<ul class="errors">).

Результат

  • при ошибках форма не отправляется и показывает список причин;
  • при успехе выводится «Успех: данные приняты».

Задание 5.

Кейс

На странице выводится таблица заказов. Требуется обеспечить семантику таблицы (thead/tbody/tfoot), корректные заголовки и доступность. Данные приходят как массив объектов.

Задание

Разработайте JS, который:

  1. принимает массив заказов { id, customer, total, status };
  2. генерирует таблицу <table> с <caption>, <thead>, <tbody>, <tfoot>;
  3. рассчитывает итоговую сумму в <tfoot>;
  4. добавляет атрибуты доступности: scope="col" для заголовков;
  5. корректно обрабатывает пустой массив (показывает строку «Нет данных»).

Результат

  • таблица создаётся динамически;
  • итоговая сумма корректна;
  • при пустых данных выводится понятное сообщение.

Задание 6.

Кейс

В проекте используется разметка с большим количеством div. Требуется перейти на семантическую структуру HTML5 (header/nav/main/section/article/footer) и одновременно сохранить “контракт” для JS через data-* и классы.

Задание

Разработайте HTML-шаблон страницы + JS, который:

  1. использует минимум: <header> <nav> <main> <section> <article> <footer>;
  2. помечает интерактивные элементы data-action="...";
  3. на JS реализует обработчик кликов по data-action (делегирование);
  4. в зависимости от action меняет состояние UI (classList toggle);
  5. логирует событие: action, элемент, время.

Результат

  • структура семантичная;
  • JS работает через data-*;
  • состояния переключаются без перезагрузки.

Задание 7.

Кейс

Нужно подключить CSS и JS корректно: стили — в <head>, скрипт — с defer, чтобы DOM был доступен. В проекте встречается ошибка, когда JS выполняется до загрузки DOM.

Задание

Разработайте минимальный пример HTML + JS, который:

  1. подключает внешний CSS и внешний JS;
  2. использует defer для скрипта;
  3. на JS выполняет поиск элемента и изменяет текст/класс;
  4. подтверждает в консоли, что DOM доступен (например, выводит количество найденных узлов);
  5. дополнительно покажите пример неправильного подключения (комментарием) и поясните, чем оно плохо.

Результат

  • код стабильно работает без DOMContentLoaded;
  • видно, что defer решает проблему порядка загрузки.

Задание 8.

Кейс

В интерфейсе есть список задач (to-do). Пользователь добавляет задачу через форму, задача появляется в списке, и её можно отметить выполненной. Требуется связка: UI(HTML) → DOM → JS(events) → (псевдо)API.

Задание

Разработайте HTML + JS, который:

  1. содержит форму добавления задачи и список <ul>;
  2. по submit добавляет задачу как <li> с кнопкой/чекбоксом;
  3. использует делегирование событий для отметки выполненной (.completed);
  4. хранит состояние задач в массиве объектов { id, text, completed };
  5. имитирует API: функция saveTask(task) возвращает Promise (setTimeout).

Результат

  • задачи добавляются и отмечаются;
  • в консоль выводится состояние массива;
  • имитация асинхронного сохранения работает.

Задание 9.

Кейс

В форме загрузки файла (например, аватар) нужно проверить тип и размер файла до отправки. HTML даёт input type="file", но проверка должна быть на JS.

Задание

Разработайте HTML + JS, который:

  1. содержит input type="file" и кнопку отправки;
  2. по выбору файла проверяет:

  3. тип (только image/png, image/jpeg);

  4. размер (например, до 2MB);
  5. при ошибке блокирует кнопку submit и показывает сообщение;
  6. при успехе отображает имя файла и размер;
  7. корректно обрабатывает ситуацию, если файл не выбран.

Результат

  • некорректные файлы не допускаются;
  • UI показывает статус проверки;
  • submit контролируется JS.

Задание 10.

Кейс

В карточке товара цена отображается в разных форматах. Нужно нормализовать ввод и вывод: пользователь вводит строку, система извлекает число, проверяет диапазон, форматирует.

Задание

Разработайте JS-функцию, которая:

  1. принимает строку (например, " 1 299,50 ₽ " или "1299.50");
  2. нормализует строку и извлекает число;
  3. валидирует: число > 0 и < 1_000_000;
  4. форматирует вывод в ru-RU через Intl.NumberFormat (валюта RUB);
  5. при ошибке возвращает диагностическое сообщение.

Результат

  • в консоль выводится либо отформатированная цена, либо ошибка;
  • корректно обрабатываются пробелы, запятые и символы валюты.

Задание 11.

Кейс

На странице есть несколько полей ввода. Требуется подсветка ошибок доступным способом: aria-invalid, сообщение через aria-describedby, фокус на первом ошибочном поле.

Задание

Разработайте HTML + JS, который:

  1. содержит форму с минимум 3 полями (name/email/phone);
  2. по submit валидирует поля и ставит aria-invalid="true" для неверных;
  3. создаёт сообщения ошибок под полями и связывает их через aria-describedby;
  4. устанавливает фокус на первое неверное поле;
  5. при исправлении поля снимает ошибку на событие input.

Результат

  • ошибки отображаются доступно;
  • фокус корректно направляется;
  • исправление снимает ошибку динамически.

Задание 12.

Кейс

Необходимо построить навигацию по странице (оглавление) на основе заголовков <h2> в контенте. Это усиливает UX и влияет на структуру документа.

Задание

Разработайте JS, который:

  1. находит все <h2> внутри <main>;
  2. гарантирует, что у каждого заголовка есть id (генерирует из текста);
  3. строит список ссылок <nav><ul>...</ul></nav>;
  4. вставляет навигацию в начало страницы;
  5. реализует плавный scroll по клику.

Результат

  • навигация строится автоматически;
  • якоря работают;
  • структура страницы становится удобнее.

Задание 13.

Кейс

Нужно продемонстрировать разницу блочных и строчных элементов и корректно управлять ими стилями. В учебном проекте важно увидеть влияние display.

Задание

Разработайте HTML + CSS + JS, который:

  1. содержит блоки и inline-элементы (div, p, span, a);
  2. через кнопки переключает стиль элементов:

  3. display: block / inline / inline-block;

  4. выводит в консоль computed style (getComputedStyle);
  5. визуально показывает изменение размеров/переноса строк;
  6. корректно работает без перезагрузки.

Результат

  • видно влияние display на layout;
  • computed style логируется для проверки.

Задание 14.

Кейс

Для UI-карточек требуется сетка: на desktop — 3 колонки, на mobile — 1 колонка. Нужны практики responsive + Grid/Flex.

Задание

Разработайте CSS + HTML, где:

  1. карточки выводятся списком (минимум 6);
  2. на ширине > 1024px — 3 колонки (Grid);
  3. на ширине <= 1024px — 2 колонки;
  4. на ширине <= 600px — 1 колонка;
  5. JS дополнительно выводит текущий breakpoint в консоль при resize (throttle).

Результат

  • сетка адаптивна;
  • логика breakpoint подтверждается в консоли.

Задание 15.

Кейс

Есть кнопка “Показать/скрыть фильтры”. Требуется корректно переключать видимость панели и состояние кнопки, без inline-стилей, только через классы.

Задание

Разработайте HTML + CSS + JS, который:

  1. содержит панель фильтров и кнопку toggle;
  2. CSS реализует скрытие через класс (например, .is-hidden);
  3. JS использует classList.toggle;
  4. обновляет aria-expanded на кнопке;
  5. сохраняет состояние в localStorage и восстанавливает при загрузке.

Результат

  • панель управляется корректно и доступно;
  • состояние переживает перезагрузку.

Задание 16.

Кейс

В интерфейсе есть “таблица прайса”, но часть данных более уместна как список определений (dl). Нужно показать правильный выбор структуры разметки.

Задание

Разработайте HTML + JS, который:

  1. получает массив характеристик товара { label, value };
  2. рендерит их как <dl><dt>...</dt><dd>...</dd></dl>;
  3. для некоторых характеристик добавляет подсказку (title);
  4. если значение отсутствует — выводит ;
  5. дополнительно генерирует JSON-объект из этих характеристик и выводит в консоль.

Результат

  • разметка семантична;
  • данные структурированы и в DOM, и в JSON.

Задание 17.

Кейс

Нужно обработать пользовательский ввод в поле поиска и фильтровать список карточек по названию. Важно: debounce, регистр, пустой ввод.

Задание

Разработайте HTML + JS, который:

  1. содержит input поиска и список карточек товаров;
  2. на событие input запускает фильтрацию с debounce 300ms;
  3. ищет по подстроке без учёта регистра;
  4. при пустом вводе показывает все карточки;
  5. выводит количество найденных результатов.

Результат

  • фильтрация работает плавно;
  • результаты и счётчик обновляются динамически.

Задание 18.

Кейс

Нужно показать работу специфичности CSS: конфликт селекторов (tag, class, id, !important). Пользователь должен увидеть, почему стиль “не применяется”.

Задание

Подготовьте HTML + CSS, где:

  1. один элемент получает конфликтующие стили минимум из 4 селекторов (tag/class/id/inline);
  2. выведите таблицу приоритетов (комментарием в CSS);
  3. JS по клику показывает “победившее” правило (через computed style) и источник (описать логикой);
  4. предложите исправление конфликта без !important (перестроение селектора/структуры);
  5. продемонстрируйте исправленный вариант.

Результат

  • видно, какое правило победило;
  • конфликт объяснён и исправлен корректно.

Задание 19.

Кейс

В проекте подключаются несколько CSS-файлов, и порядок подключения ломает тему. Нужно гарантировать, что theme.css подключается последним.

Задание

Разработайте JS, который:

  1. находит все <link rel="stylesheet"> в <head>;
  2. проверяет наличие theme.css;
  3. если theme.css не последний — перемещает его в конец <head>;
  4. логирует порядок файлов до/после;
  5. не ломает работу при отсутствии theme.css (выводит предупреждение).

Результат

  • theme.css всегда последним;
  • порядок подтверждён логом.

Задание 20.

Кейс

Нужно создать интерактивную “hero section” с кнопкой CTA и простой анимацией hover, при этом соблюсти доступность фокуса и контраст.

Задание

Разработайте HTML + CSS + JS, который:

  1. создаёт hero-блок: заголовок, текст, CTA-кнопка;
  2. CSS делает transition/transform для hover;
  3. добавляет :focus-visible стиль (не хуже hover);
  4. JS по клику на CTA имитирует запрос (Promise + setTimeout) и блокирует кнопку на время;
  5. по завершении показывает сообщение “Заявка отправлена”.

Результат

  • анимация есть, UX корректен;
  • кнопка блокируется во время “запроса”;
  • сообщение появляется без перезагрузки.

Задание 21.

Кейс

Нужно загрузить список пользователей с API (Fetch), обработать ошибки, отрендерить в DOM. В учебной версии API можно заменить мок-данными.

Задание

Разработайте JS, который:

  1. делает fetch("/api/users") (если нет — используйте мок через Promise);
  2. обрабатывает статусы HTTP (не 2xx → ошибка);
  3. парсит JSON и рендерит список <ul>;
  4. показывает загрузку (loader) на время запроса;
  5. при ошибке выводит сообщение пользователю (в DOM) и логирует детали.

Результат

  • список пользователей появляется;
  • loader исчезает;
  • ошибки отображаются корректно.

Задание 22.

Кейс

В форме оформления заказа нужно собрать данные в объект и отправить как JSON на API. При этом важно различать GET/POST и корректно выставлять headers.

Задание

Разработайте HTML + JS, который:

  1. содержит форму: customerName, address, deliveryDate, comment;
  2. по submit собирает данные в объект;
  3. валидирует обязательные поля;
  4. отправляет POST-запрос fetch("/api/orders", { method:"POST", headers:{...}, body: JSON.stringify(...) });
  5. обрабатывает ответ: успех/ошибка, показывает статус пользователю.

Результат

  • отправка без перезагрузки;
  • JSON формируется корректно;
  • UI сообщает результат.

Задание 23.

Кейс

Нужно показать работу data-* как контракта HTML → JS. На карточках товаров есть кнопки действий: add-to-cart, favorite, compare.

Задание

Разработайте HTML + JS, который:

  1. создаёт карточки товаров (минимум 4), где кнопки имеют data-action;
  2. одним обработчиком (делегирование) определяет действие;
  3. обновляет состояние карточки (класс + счетчик в шапке);
  4. сохраняет состояние (избранное/корзина) в localStorage;
  5. при загрузке восстанавливает состояния из localStorage.

Результат

  • действия работают;
  • состояние сохраняется;
  • HTML остаётся “контрактом” для логики.

Задание 24.

Кейс

Есть таблица с объединением ячеек (rowspan/colspan) и группировкой колонок (colgroup). Нужно построить её из данных и обеспечить семантику.

Задание

Создайте HTML-таблицу “Отчёт по продажам”, где:

  1. используется <colgroup> для групп колонок (например, “Суммы”);
  2. есть <thead>, <tbody>, <tfoot>;
  3. в заголовке применяются rowspan/colspan;
  4. JS заполняет <tbody> из массива объектов;
  5. итоговые суммы считаются в <tfoot>.

Результат

  • таблица сложная и корректная;
  • суммы совпадают с данными;
  • структура семантична.

Задание 25.

Кейс

Нужно проверить базовую защиту от XSS в пользовательском вводе комментария: нельзя вставлять HTML как разметку (только текст). Ошибка часто возникает при использовании innerHTML.

Задание

Разработайте HTML + JS, который:

  1. содержит textarea для комментария и кнопку “Добавить”;
  2. добавляет комментарии в список;
  3. вставляет текст только через textContent (не innerHTML);
  4. демонстрирует тест: строка с <script> не должна выполняться и не должна превращаться в DOM;
  5. логирует предупреждение, если пользователь вводит подозрительные теги (простая RegExp-проверка).

Результат

  • комментарии безопасно отображаются;
  • XSS-вставки не исполняются;
  • предупреждение выводится при попытке ввода HTML.

Задание 26.

Кейс

В приложении нужно различать “пустые” HTML-элементы (void) и обычные. Частая ошибка — закрывать void-элементы неправильно или пытаться вкладывать контент.

Задание

Разработайте мини-проверку на JS, которая:

  1. принимает строку HTML (шаблон) с элементами img, input, br, meta;
  2. парсит её в DOM (через template);
  3. проверяет, что void-элементы не содержат детей;
  4. если обнаружено нарушение (например, img с childNodes) — выводит ошибку;
  5. дополнительно выводит список всех найденных void-элементов и их атрибутов.

Результат

  • выявляются нарушения структуры;
  • выводится отчёт по void-элементам.

Задание 27.

Кейс

Нужно создать компонент формы входа, где при вводе email автоматически приводится к нижнему регистру, а пробелы удаляются. Это снижает ошибки пользователей.

Задание

Разработайте HTML + JS, который:

  1. содержит поле email и пароль;
  2. на событие input у email выполняет нормализацию:

  3. trim;

  4. удаление пробелов внутри;
  5. приведение к lowerCase;
  6. валидирует email через RegExp;
  7. отображает статус “ok/ошибка” рядом с полем;
  8. блокирует submit при ошибке email.

Результат

  • email нормализуется автоматически;
  • статус отображается динамически;
  • submit доступен только при корректном email.

Задание 28.

Кейс

Нужно показать практику “HTML как контракт для JS”: элементы должны иметь стабильные id/class, чтобы JS-логика не ломалась при изменении визуального оформления.

Задание

Разработайте небольшой UI “сервис заявок”, где:

  1. HTML содержит: фильтр статуса (select), список заявок, форму добавления;
  2. все ключевые элементы имеют id и data-*;
  3. JS реализует:

  4. добавление заявки;

  5. фильтрацию по статусу;
  6. смену статуса заявки;
  7. данные хранятся в массиве объектов;
  8. DOM перерисовывается функцией render().

Результат

  • функционал работает полностью;
  • структура HTML остаётся предсказуемой для JS;
  • есть явная мини-архитектура UI → DOM → JS.

Задание 29.

Кейс

Нужно оптимизировать производительность UI: изображения должны лениво загружаться, а тяжелые элементы — подгружаться по мере необходимости.

Задание

Разработайте HTML + JS, который:

  1. выводит список карточек с изображениями (минимум 10);
  2. для img использует loading="lazy" и фиксированные размеры;
  3. дополнительно использует IntersectionObserver для добавления класса анимации при появлении на экране;
  4. при отсутствии поддержки IntersectionObserver — использует fallback (без анимации);
  5. логирует в консоль элементы, которые “вошли” в viewport.

Результат

  • lazy loading работает;
  • карточки анимируются при появлении;
  • есть fallback.

Задание 30.

Кейс

Нужно спроектировать клиентскую часть мини-приложения “Каталог курсов” (LMS): HTML задаёт layout и контракт, JS обрабатывает события, API отдаёт данные, UI рендерит карточки и фильтры.

Задание

Разработайте HTML + JS (можно с мок-API), который:

  1. содержит:

  2. поле поиска,

  3. фильтр категории,
  4. контейнер карточек курсов,
  5. индикатор загрузки;
  6. загружает курсы через функцию fetchCourses() (Promise → массив объектов {id, title, category, level});
  7. рендерит карточки курсов в DOM (без innerHTML для пользовательских данных);
  8. реализует фильтрацию по поиску + категории (с debounce);
  9. показывает “нет результатов”, если фильтр ничего не нашёл, и корректно обрабатывает ошибки (try/catch + UI сообщение).

Результат

  • каталог загружается и фильтруется без перезагрузки;
  • UI показывает загрузку/ошибки/пустой результат;
  • соблюдена архитектура: UI(HTML) → DOM → JS(events) → API → data.