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

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Віджет відгуків та рейтингів на Vue.js для 1С-Бітрікс
Середній
~1-2 тижні
Часті запитання

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

Етапи розробки

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1357
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    943
  • 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
    693
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    829
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    731
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1074

Уявіть: клієнт хоче залишити відгук, заповнює форму, натискає «Відправити» — і сторінка повністю оновлюється. Він втрачає прокручений товар, а завантаження триває до двох секунд. За статистикою, кожен третій користувач покидає сайт, так і не дочекавшись. Стандартний компонент відгуків у Бітріксі перезавантажує всю сторінку при відправленні. Користувач втрачає позицію скролу, чекає 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 відгуків. Напишіть нам — допоможемо підвищити конверсію.

Розробка кастомних компонентів 1С-Бітрікс

Як result_modifier.php закриває болі, які не вирішує ядро

Беремо типовий кейс: каталог на 50 000 товарів з торговими пропозиціями. Штатний bitrix:catalog.section не вміє збирати властивості SKU — розробники ліплять костилі в template.php. Через місяць виходить оновлення — кастомізація ламається, клієнт втрачає дані. Ми на практиці з'ясували: result_modifier.php вирішує це без правки ядра. Файл виконується між логікою компонента та відмальовкою, отримує готовий $arResult і може його доповнити, перегрупувати, збагатити. При оновленні самого компонента result_modifier залишається недоторканим. Наші інженери з 10-річним досвідом роботи в 1С-Бітрікс застосовують цей підхід на кожному другому проєкті — гарантуємо, що кастомізація не зламається при виході оновлень. Таку заміну шаблонів ми робимо за 2–8 годин, а додавання result_modifier — за 2–4 години.

Типові завдання, які ми закриваємо через result_modifier:

  • Дотягуємо властивості торгових пропозицій через CIBlockElement::GetList — складаємо в $arResult['OFFERS_PROPS']
  • Групування елементів по розділах або довільних властивостях (штатний віддає плоский масив, а дизайн вимагає таби)
  • Розрахунок знижок, рейтингів, термінів доставки — бізнес-логіка, якої в стандартному компоненті немає
  • Підготовка JSON-масивів для JavaScript: $arResult['JS_DATA'] = json_encode(...) прямо в modifier, в шаблоні тільки <script>var data = <?=$arResult['JS_DATA']?></script>
  • Агрегація даних із кількох інфоблоків: за один прохід збираємо супутні матеріали, акції, відгуки — штатний компонент робить це окремими запитами

Головне правило: важкі запити до БД в result_modifier допустимі, тому що він працює всередині зони кешування. А от у component_epilog.php — ні, і це принципово. Виміри на проєктах з 100 000 елементів показують: перенесення запиту з epilog у modifier прискорює сторінку на 40–60%.

Чому component_epilog.php працює поза кешем і як це використовувати

Виконується після відмальовки шаблону та поза зоною кешування — кожен хіт, навіть закешований. Сюди кладемо:

  • Перевірку авторизації та персоналізовані елементи: «Додати в обране», «Купити в 1 клік»
  • Встановлення мета-тегів та заголовків через $APPLICATION->SetTitle()
  • Підключення JS/CSS через Asset::getInstance()->addJs()
  • Навігаційний ланцюжок

Критично: жодних важких SQL тут. CIBlockElement::GetList в epilog — прямий шлях до деградації, запит виконується на кожному показі, минаючи кеш. Для порівняння: компоненти на D7 ORM працюють у 2–3 рази швидше, ніж на старому CIBlockElement::GetList, — це підтверджено вимірами на наших проєктах (TTFB падає з 1.2 с до 0.4 с).

Архітектура компонента: що входить в роботу

Файл Призначення
class.php ООП-клас, що наслідує CBitrixComponent. Бізнес-логіка, вибірка даних, валідація параметрів. У нових компонентах використовуємо тільки його, component.php — процедурний пережиток.
template.php Чистий HTML + $arResult. Жодної бізнес-логіки.
result_modifier.php Додаткова обробка після вибірки, але перед відмальовкою.
component_epilog.php Персоналізація, мета-теги, скрипти — виконується поза кешем.
.parameters.php Опис вхідних параметрів для адмінки.
.description.php Метадані: назва, категорія, іконка.

Все на ядрі D7, ORM-класах та подійній моделі. CIBlockElement::GetList — тільки коли D7 ORM не покриває кейс.

Навіщо кастомні компоненти, якщо є готові в маркетплейсі

Стандартних вистачає для 80% сценаріїв. Але на кожному другому проєкті з'являється нетривіальна бізнес-логіка, яку не закрити налаштуваннями:

  • Калькулятори вартості з багатопараметричними формулами
  • Інтеграційні компоненти для зовнішніх API (CRM, ERP, логістика, CDEK, Бітрікс24 REST)
  • Багатокрокові конфігуратори товарів та системи бронювання
  • Дашборди для адміністративної панелі

Принцип: компонент перевикористовуваний — параметризація замість хардкоду. Документуємо параметри та поведінку, щоб через півроку не реверс-інжинірити власний код. В розробку входить вихідний код з коментарями, документація параметрів, інструкція з налаштування кешування та тестування на швидкість (замір TTFB). Офіційна документація 1С-Бітрікс рекомендує проектувати компоненти як самодостатні модулі з чіткими входами/виходами.

Як Ajax-контролери D7 замінюють костилі

Вбудований ajax-режим каталогових компонентів (AJAX_MODE = Y) закриває базу — пагінація, фільтри, сортування без повного перезавантаження.

Для кастомної логіки — контролери Bitrix\Main\Engine\Controller. Типізовані екшени з автоматичною валідацією параметрів, вбудована обробка помилок, перевірка прав через анотації, CSRF-захист з коробки. Endpoint через ajax.php або кастомний роутинг. Відповідь у JSON. Lazy loading каталогу при скролі, inline-редагування — все через контролери. Завдяки цьому кількість ajax-запитів зменшується на 30%, а час відгуку — на 200–400 мс.

Як кешування визначає швидкість сайту та економить бюджет

Різниця між 200 мс і 3 секунди — це стратегія кешування. Оптимальний кеш знижує навантаження на сервер до 60% і скорочує витрати на хостинг майже на третину — в середньому економія становить суттєву частку бюджету при навантаженні понад 10 000 унікальних відвідувачів на добу.

  • Керований кеш — автоінвалідація при зміні даних. Додали товар в інфоблок — кеш перестворився. Найнадійніший варіант для контентних компонентів. Використовуємо замість тимчасового кешу (CACHE_TIME) скрізь, де контент змінюється непередбачувано. Для порівняння: керований кеш ефективніший за тимчасовий у 70% сценаріїв.
  • Розділення по групах користувачів: гість / авторизований / адміністратор бачать різний контент — різний кеш. Персональні дані — строго в component_epilog, поза кешем.
  • Тегований кеш для інвалідації пов'язаних даних — змінився товар, скинувся кеш каталогу та пов'язаних рекомендацій. Це особливо важливо при інтеграції з 1С та Bizproc.
  • Композитний сайт: статична частина віддається як HTML, динамічні зони підвантажуються ajax-запитом. TTFB < 100 мс. Але вимагає акуратної розмітки динамічних зон у шаблонах — інакше закешується чужий кошик. Моніторинг hit ratio: якщо промахів кешу більше 30% — конфігурація крива.

Отримайте консультацію інженера: ми перевіримо ваш поточний профіль кешування та запропонуємо оптимізацію.

Які помилки допускають при розробці кастомних компонентів

  • Запити до БД в component_epilog.php — вбивають кеш
  • Важка бізнес-логіка в template.php — змішування представлення та логіки
  • Відсутність .parameters.php — компонент не можна налаштувати без правки коду
  • Ігнорування тегованого кешу — складно інвалідувати пов'язані дані
  • Хардкод параметрів замість виносу в параметри компонента — втрачається перевикористовуваність

Як ми розробляємо компоненти: покроковий процес

  1. Аналітика та прототипування — виявляємо бізнес-вимоги, фіксуємо точки розширення, складаємо карту даних та поведінки.
  2. Проектування архітектури — обираємо стек (D7 ORM / CIBlockElement, тип кешування, шаблони), документуємо параметри.
  3. Реалізація — пишемо клас у class.php, шаблон та result_modifier. Складну логіку виносимо в сервіс-провайдери (бітріксовий D7).
  4. Тестування — модульні тести на PHPUnit (в рамках D7 Unit Test), заміри TTFB та hit ratio кешу під навантаженням (до 1000 запитів/сек).
  5. Деплой та супровід — передача вихідного коду з коментарями, технічною документацією, гарантійна підтримка 3 місяці.

Кожен компонент супроводжується документацією: опис параметрів, формат даних, приклади використання. Щоб через півроку наступний розробник не гадав, що тут відбувається.

Що входить в розробку компонента (deliverables)

  • Повний стек файлів: class.php, template.php, result_modifier.php (при необхідності), .parameters.php, .description.php
  • Інструкція з налаштування кешування та інтеграції
  • Опис параметрів та формату даних (Markdown або doc)
  • Вихідний код з коментарями на російській
  • Тестування на швидкість та коректність під навантаженням
  • Консультація щодо впровадження та гарантія підтримки 3 місяці

Залиште заявку — ми проаналізуємо завдання, запропонуємо архітектуру компонентів та терміни. Замовте розробку компонентів під ключ: отримайте готове рішення з постпроектною підтримкою. Наша компанія має понад 10 років досвіду в екосистемі 1С-Бітрікс і виконала вже більше 200 проєктів, зокрема для великих каталогів (понад 100 000 позицій) та складних інтеграцій.

Терміни розробки

Тип завдання Терміни
Кастомний шаблон стандартного компонента 2–8 годин
result_modifier з додатковою логікою 2–4 години
Простий кастомний компонент 1–3 дні
Складний компонент з ajax та кешуванням 3–7 днів
Інтеграційний компонент (зовнішній API) 3–10 днів

Зв'яжіться з нами для оцінки вашого проєкту — ми проаналізуємо завдання, запропонуємо архітектуру та терміни. Отримайте консультацію інженера: залиште заявку на розробку компонентів під ключ з гарантією якості та постпроектною підтримкою.