Войти Регистрация
Код-ревью

42. Галерея фото из отзывов на карточке Ozon

Лёгкая

JavaScript · 41 строк

Под карточкой товара — лента фото из отзывов. При прокрутке к низу страницы подгружается следующая страница по 24 фото, по клику фото открывается крупно с оценкой и текстом.

Сайт — SPA: при переходе на другой товар старая галерея вызывает destroy(), создаётся новая. Отзывы-вопросы с фото приходят с rating: null. Отметьте строки с ошибками.

В работе: Блок «Фото покупателей» на карточке товара в веб-версии.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Ответ один на подход: после него показываем разбор.
DOMXSSобработчики событийfetchбесконечная прокрутка

Источник: наша задача на данных Ozon: отзывы и карточка товара. Условие пересказано своими словами.

  1. // Галерея фото из отзывов на карточке товара, подгрузка при прокрутке
  2. class ReviewGallery {
  3. constructor(root, productId) {
  4. this.root = root;
  5. this.productId = productId;
  6. this.page = 1;
  7. this.loading = false;
  8. window.addEventListener("scroll", () => this.onScroll());
  9. }
  10. async onScroll() {
  11. const nearBottom = window.innerHeight + window.scrollY > document.body.offsetHeight - 600;
  12. if (!nearBottom || this.loading) return;
  13. this.loading = true;
  14. const resp = await fetch(`/api/products/${this.productId}/review-photos?page=${this.page}`);
  15. const data = await resp.json();
  16. this.page++;
  17. this.loading = false;
  18. this.render(data.items);
  19. }
  20. render(items) {
  21. for (const item of items) {
  22. const card = document.createElement("figure");
  23. card.innerHTML = `<img src="${item.thumb}" alt="">
  24. <figcaption>${item.author}: ${item.text}</figcaption>`;
  25. card.addEventListener("click", () => this.open(item));
  26. this.root.appendChild(card);
  27. }
  28. }
  29. open(item) {
  30. const rating = item.rating.toFixed(1);
  31. document.getElementById("viewer-img").src = item.full;
  32. document.getElementById("viewer-caption").textContent = `${rating} ★ ${item.text}`;
  33. }
  34. destroy() {
  35. this.root.innerHTML = "";
  36. }
  37. }