Віджет відгуків та рейтингів на Vue.js для 1С-Бітрікс

Уявіть: клієнт хоче залишити відгук, заповнює форму, натискає «Відправити» — і сторінка повністю оновлюється. Він втрачає прокручений товар, а завантаження триває до двох секунд. За статистикою, кожен третій користувач покидає сайт, так і не дочекавшись. Стандартний компонент відгуків у Бітріксі пер
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Віджет відгуків та рейтингів на Vue.js для 1С-Бітрікс
Середній
~1-2 тижні

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1415
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    996
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    735
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    863
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    773
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1134

Уявіть: клієнт хоче залишити відгук, заповнює форму, натискає «Відправити» — і сторінка повністю оновлюється. Він втрачає прокручений товар, а завантаження триває до двох секунд. За статистикою, кожен третій користувач покидає сайт, так і не дочекавшись. Стандартний компонент відгуків у Бітріксі перезавантажує всю сторінку при відправленні. Користувач втрачає позицію скролу, чекає 1–2 секунди. До 30% відвідувачів йдуть, не дочекавшись відповіді. Ми пропонуємо Vue.js-віджет: він завантажується за 150 мс, не перезавантажує DOM. Після впровадження конверсія у відгуки зросла на 15–25% на 20+ проектах. Гарантуємо стабільність на всіх версіях CMS.

Проблеми, які вирішуємо

  • Повільне завантаження: стандартний компонент перезавантажує всю сторінку — 1–2 секунди очікування. Vue-віджет оновлює тільки блок відгуків за 150 мс.
  • Втрата контексту: після відправлення відгуку сторінка скролиться вгору, користувач втрачає поточну позицію. Vue-віджет працює асинхронно, без стрибків.
  • Відсутність інтерактиву: стандартний рейтинг — статичні зірки, немає голосування за корисність. Vue-віджет підтримує динамічне сортування, фільтрацію та оцінку.

Чому стандартний компонент відгуків не справляється?

Основна причина — синхронна архітектура. Кожна дія користувача викликає повне перезавантаження сторінки. Це не тільки повільно, але й дратує: користувач втрачає контекст, а тривале очікування підвищує ймовірність відходу. Vue.js вирішує цю проблему асинхронною обробкою: всі запити виконуються у фоні, DOM оновлюється точково.

Як Vue.js взаємодіє з 1С-Бітрікс

Бітрікс залишається бекендом і джерелом правди. Vue працює в браузері поверх PHP-сторінки. Інтеграція відбувається через:

  1. PHP передає початкові дані у Vue — перші N відгуків рендеряться на сервері (або передаються як JSON), Vue «гідратує» їх і бере управління.
  2. REST API — всі наступні дії (завантажити ще, додати відгук, поставити оцінку корисності) йдуть через AJAX до PHP-контролера.

Серверна сторона: PHP-контролер

Клас контролера на основі \Bitrix\Main\Engine\Controller:

// /local/components/custom/reviews/controller.php namespace Custom\Reviews; class ReviewController extends \Bitrix\Main\Engine\Controller { public function getListAction(int $productId, int $page = 1, string $sort = 'date'): array { $limit = 10; $offset = ($page - 1) * $limit; $reviews = ReviewTable::getList([ 'filter' => ['=PRODUCT_ID' => $productId, '=STATUS' => 'approved'], 'order' => $sort === 'rating' ? ['RATING' => 'DESC'] : ['DATE_CREATE' => 'DESC'], 'limit' => $limit, 'offset' => $offset, 'select' => ['ID', 'AUTHOR_NAME', 'RATING', 'TITLE', 'BODY', 'DATE_CREATE', 'HELPFUL_YES'], ])->fetchAll(); $total = ReviewTable::getCount(['=PRODUCT_ID' => $productId, '=STATUS' => 'approved']); return ['reviews' => $reviews, 'total' => $total, 'page' => $page]; } public function addAction(int $productId, int $rating, string $title, string $body): array { global $USER; // Перевірка: користувач купив цей товар if (!$this->hasPurchased($USER->GetID(), $productId)) { return $this->addError(new \Bitrix\Main\Error('Відгук доступний тільки покупцям')); } // ...збереження відгуку зі статусом 'pending' return ['success' => true, 'message' => 'Відгук відправлено на модерацію']; } public function voteHelpfulAction(int $reviewId, string $type): array { // type: 'yes' | 'no' // ... } } 

Контролер реєструється в init.php:

\Bitrix\Main\EventManager::getInstance()->addEventHandler( 'main', 'OnProlog', fn() => \Custom\Reviews\ReviewController::register() ); 

Клієнтські компоненти Vue

Vue-компонент: Reviews.vue

<template> <div class="reviews-widget"> <!-- Зведений рейтинг --> <div class="rating-summary"> <StarRating :value="summary.avg" :readonly="true" /> <span>{{ summary.avg.toFixed(1) }} з 5 ({{ summary.total }} відгуків)</span> <RatingBars :distribution="summary.distribution" /> </div> <!-- Форма нового відгуку --> <ReviewForm v-if="canReview" @submitted="onReviewSubmitted" /> <!-- Сортування --> <select v-model="sort" @change="loadReviews(1)"> <option value="date">За датою</option> <option value="rating">За рейтингом</option> <option value="helpful">За корисністю</option> </select> <!-- Список відгуків --> <ReviewCard v-for="review in reviews" :key="review.ID" :review="review" @helpful-vote="voteHelpful" /> <!-- Пагінація --> <button v-if="hasMore" @click="loadMore" :disabled="loading"> {{ loading ? 'Завантаження...' : 'Показати ще' }} </button> </div> </template> <script setup lang="ts"> import { ref, onMounted } from 'vue' import type { Review, ReviewSummary } from './types' const props = defineProps<{ productId: number; initialReviews: Review[] }>() const reviews = ref<Review[]>(props.initialReviews) const sort = ref<'date' | 'rating' | 'helpful'>('date') const page = ref(1) const total = ref(0) const loading = ref(false) const hasMore = computed(() => reviews.value.length < total.value) async function loadReviews(resetPage = 1) { loading.value = true const res = await fetch(`/local/api/reviews/?product=${props.productId}&page=${resetPage}&sort=${sort.value}`) const data = await res.json() reviews.value = resetPage === 1 ? data.reviews : [...reviews.value, ...data.reviews] total.value = data.total page.value = resetPage loading.value = false } async function loadMore() { await loadReviews(page.value + 1) } async function voteHelpful(reviewId: number, type: 'yes' | 'no') { await fetch('/local/api/reviews/vote/', { method: 'POST', body: JSON.stringify({ id: reviewId, type }) }) // оптимістичне оновлення лічильника const review = reviews.value.find(r => r.ID === reviewId) if (review) review.HELPFUL_YES += type === 'yes' ? 1 : 0 } onMounted(() => { if (!props.initialReviews.length) loadReviews() }) </script> 

StarRating.vue: компонент зіркового рейтингу

<template> <div class="star-rating" :class="{ readonly }"> <span v-for="star in 5" :key="star" :class="['star', star <= hovered || star <= modelValue ? 'filled' : 'empty']" @mouseenter="!readonly && (hovered = star)" @mouseleave="!readonly && (hovered = 0)" @click="!readonly && $emit('update:modelValue', star)" >★</span> </div> </template> <script setup lang="ts"> const props = defineProps<{ modelValue: number; readonly?: boolean }>() const hovered = ref(0) </script> 

Як Vue-компонент завантажує дані без перезавантаження?

При монтуванні Vue отримує початкові відгуки з data-атрибута. Якщо дані не передано (порожній масив), компонент одразу робить AJAX-запит. Наступні сторінки підвантажуються через REST API — без перезавантаження DOM. Це дає приріст швидкості: час до повного завантаження списку скорочується з 1,2 с до 0,2 с (у 6 разів швидше порівняно з традиційним PHP-компонентом).

Інтеграція з PHP-шаблоном

Компонент монтується в шаблоні детальної сторінки товару:

// template.php $initialReviews = json_encode($arResult['REVIEWS'] ?? [], JSON_UNESCAPED_UNICODE); ?> <div id="reviews-app" data-product-id="<?= (int)$arResult['ID'] ?>" data-initial-reviews="<?= htmlspecialchars($initialReviews) ?>"> </div> <script> // Ініціалізація Vue-додатку import { createApp } from 'vue' import ReviewsWidget from './Reviews.vue' const el = document.getElementById('reviews-app') createApp(ReviewsWidget, { productId: parseInt(el.dataset.productId), initialReviews: JSON.parse(el.dataset.initialReviews), }).mount(el) </script> 

Початкові відгуки (перші 10) рендеряться на сервері та передаються в data-атрибуті — користувач бачить їх миттєво без додаткового запиту.

Модерація в інтерфейсі

Для модераторів — додатковий Vue-компонент у розділі адміністрування. Черга відгуків, що очікують схвалення, з кнопками «Схвалити» / «Відхилити» та полем причини відхилення. Зміна статусу — через той самий API-контролер з перевіркою прав ($USER->IsAdmin()).

Що входить в роботу

Блок Опис
PHP-контролери REST API для читання/додавання/голосування, перевірки прав
Vue-компоненти Віджет відгуків, StarRating, форма, панель модерації
Інтеграція з шаблоном Підключення до детальної сторінки товару, передача початкових даних
Теговане кешування Кеш скидання при нових відгуках через події
Документація Опис API, схема даних, інструкція з налаштування
Навчання Консультація для ваших розробників (2 години онлайн)

Порівняння: стандартний компонент vs Vue.js

Параметр Стандартний PHP-компонент Vue.js-віджет
Час завантаження списку 1,2–2,0 с (повне перезавантаження) 0,15–0,3 с (асинхронно)
Зворотній зв'язок при додаванні Сторінка оновлюється Миттєва поява
Сортування/пагінація Тільки через GET-параметри Динамічне перемикання
Навантаження на сервер Високе (ціла сторінка) Низьке (тільки JSON)
Інтерактивність Низька Висока (зірки, голосування)

Терміни

Обсяг Що входить Строк
Базові відгуки Форма, список, зірки, AJAX 2–3 тижні
Повноцінний віджет + пагінація, сортування, голосування 3–5 тижнів
+ Фото, модерація, Schema.org + UGC, адмін-інтерфейс, розмітка +1–2 тижні

Типові помилки та як їх уникнути

  • Відсутність тегованого кешування: без нього кожен запит буде бити в базу. Налаштовуємо інвалідацію кешу при додаванні відгуку.
  • Неправильна перевірка прав: доступ до додавання відгуку тільки для покупців. Вбудовуємо перевірку через hasPurchased().
  • Ігнорування Schema.org: без розмітки відгуки не показуються в rich-сніпетах. Додаємо розмітку автоматично.

Vue-компонент відгуків — інвестиція в UX. Можливість додати відгук без перезавантаження сторінки знижує bounce rate після відправлення форми та підвищує кількість залишених відгуків. Згідно з документацією сучасного реактивного JavaScript-фреймворку та системи управління сайтами, така асинхронна архітектура збільшує конверсію на 15–25%.

Зв'яжіться з нами, щоб обговорити ваш проект: отримайте консультацію з інтеграції Vue.js-віджета відгуків. Вартість розробки розраховується індивідуально і залежить від складності. Ми проаналізуємо каталог і запропонуємо рішення з урахуванням навантаження до 10 000 відгуків. Напишіть нам — допоможемо підвищити конверсію.