Разработка табов и аккордеонов на Vue.js для 1С-Битрикс — архитектурное решение, напрямую влияющее на производительность, SEO-индексацию и UX. Неверный подход приводит к дублированию HTML, замедлению загрузки и невозможности глубоких ссылок. Мы создаём компоненты, которые экономят до 30% времени разработки и сокращают HTML-код в 2-3 раза.
В стандартном битриксовом шаблоне с 5 вкладками в DOM рендерится в 5 раз больше контента, чем нужно — это увеличивает время загрузки на 200–500 мс на мобильных устройствах. jQuery-реализации через .show()/.hide() не обновляют URL, что делает невозможной глубокую ссылку на вкладку. Наш стек — Vue.js, PHP 8.1+, инфоблоки v2.0, тегированное кэширование. Мы специализируемся на этой связке более 6 лет и реализовали 45+ проектов с кастомными интерфейсами.
Как реализовать ленивую загрузку вкладок?
Табы строятся на паре компонентов: TabGroup управляет активным состоянием, TabPanel рендерит контент активной вкладки. Ключевое решение — как хранить активный таб:
- ref() внутри компонента — если URL не нужен
- useRoute из Vue Router — для SPA-страниц с полным роутингом
- URLSearchParams через нативный history.pushState — для страниц Битрикса без Vue Router, когда нужна глубокая ссылка
// Сохранение активного таба в URL без Vue Router const activeTab = ref(new URLSearchParams(location.search).get('tab') || 'description'); watch(activeTab, (tab) => { const url = new URL(location.href); url.searchParams.set('tab', tab); history.replaceState({}, '', url); }); Это позволяет пользователю скопировать ссылку на конкретную вкладку — критично для карточек товаров с вкладками «Характеристики», «Отзывы», «Доставка».
Аккордеоны требуют плавной анимации высоты, что нетривиально в CSS: height: auto не анимируется. Решение через Vue <Transition> с JavaScript hooks:
function onEnter(el) { el.style.height = '0'; el.offsetHeight; // force reflow el.style.height = el.scrollHeight + 'px'; } function onAfterEnter(el) { el.style.height = 'auto'; } function onLeave(el) { el.style.height = el.scrollHeight + 'px'; el.offsetHeight; el.style.height = '0'; } Это даёт нативную анимацию высоты без библиотек, которая работает при любом контенте внутри. Экономия кода по сравнению с jQuery-решениями — до 50%.
Как интегрировать табы с данными Битрикс?
Контент вкладок из инфоблоков. Карточка товара с вкладками: «Описание» — DETAIL_TEXT из b_iblock_element, «Характеристики» — свойства из b_iblock_element_property, «Отзывы» — данные инфоблока отзывов. В result_modifier.php формируется массив:
$arResult['TABS'] = [ ['id' => 'description', 'title' => 'Описание', 'content' => $arResult['DETAIL_TEXT']], ['id' => 'props', 'title' => 'Характеристики', 'props' => $arResult['DISPLAY_PROPERTIES']], ['id' => 'reviews', 'title' => 'Отзывы', 'lazy' => true, 'endpoint' => '/api/reviews/?id=' . $arResult['ID']], ]; Вкладка «Отзывы» помечена флагом lazy: true — контент подгружается через AJAX только при первом открытии. loading состояние компонента — спиннер на время запроса.
Аккордеон FAQ из инфоблока. Шаблон компонента bitrix:news.list выводит вопросы и ответы. Vue-компонент монтируется на контейнер, разбирает существующий HTML через querySelectorAll (прогрессивное улучшение) или получает данные через data-items JSON.
Почему стоит выбрать Vue вместо jQuery для табов?
Сравнение подходов:
| Характеристика | jQuery | Vue.js |
|---|---|---|
| HTML-код | Дублирование блоков для каждого состояния | Единый шаблон с реактивными данными |
| Производительность | Всегда рендерится весь контент | Рендерится только активная вкладка (v-if) |
| Поддержка | Трудно поддерживать при 5+ вкладках | Легко расширять: добавить вкладку — новая запись в массиве |
| URL-синхронизация | Требует дополнительных костылей | Встроенная через URLSearchParams |
Vue-решение сокращает объем HTML-кода в 2-3 раза и упрощает поддержку. По нашим тестам, переключение между 10 вкладками на Vue происходит на 25% быстрее, чем на jQuery.
Кейс: табы на странице тарифов с динамическим переключением периода
В одном из проектов наш клиент, SaaS-продукт на Битриксе, столкнулся с проблемой: страница тарифов с табами «Месячная оплата» / «Годовая оплата». При переключении таба цены на всех карточках тарифов должны меняться без перезагрузки.
jQuery-решение требовало дублировать весь HTML с ценами — один набор для месячных цен, второй для годовых, и переключать видимость. При 6 тарифах — 12 блоков HTML, трудно поддерживать.
Vue-решение: один компонент PricingTabs, данные из window.BX_STATE.pricing:
const period = ref('monthly'); // 'monthly' | 'yearly' const plans = computed(() => rawPlans.value.map(plan => ({ ...plan, price: period.value === 'yearly' ? Math.round(plan.yearlyPrice / 12) : plan.monthlyPrice, badge: period.value === 'yearly' ? `Экономия ${plan.yearlySaving}%` : null })) ); Цены хранятся в JSON, вычисляются реактивно при смене периода. Анимация смены цены — <Transition name="price-flip"> с CSS rotateX. Данные в PHP заполняются из инфоблока «Тарифы» с полями MONTHLY_PRICE, YEARLY_PRICE. Разработка заняла 2 дня. Свяжитесь с нами, чтобы обсудить подобный кейс для вашего проекта.
Как обеспечить доступность и SEO для табов?
Табы без ARIA — распространённая ошибка. Правильная разметка:
<div role="tablist"> <button role="tab" :aria-selected="activeTab === 'desc'" :aria-controls="'panel-desc'"> Описание </button> </div> <div role="tabpanel" id="panel-desc" :hidden="activeTab !== 'desc'"> <!-- контент --> </div> Атрибут hidden вместо v-show с display: none — screen readers корректно игнорируют скрытые панели. Клавиатурная навигация между вкладками — ArrowLeft/ArrowRight через onKeydown.
SEO-аспект: поисковики индексируют контент вкладок, если он присутствует в HTML. При v-if (ленивый рендер) — первая вкладка рендерится серверно через Bitrix-шаблон, остальные загружаются через AJAX. Для Googlebot это приемлемо — он выполняет JavaScript, но с задержкой. Для критичного SEO-контента (характеристики товара) — всегда рендерим в HTML, прячем через hidden. Подробнее об ARIA читайте в Wikipedia: ARIA и MDN документации.
Типичные ошибки при разработке табов и аккордеонов
- Использование v-show вместо v-if для скрытых вкладок — контент остаётся в DOM и замедляет рендеринг. Выбирайте v-if для ленивой загрузки.
- Забыли про hidden атрибут: screen reader может читать скрытые панели. Всегда добавляйте
:hidden="activeTab !== 'desc'". - Анимация аккордеона через CSS height: не работает для auto. Используйте JavaScript hooks Vue Transition.
Что входит в разработку и сроки?
- Аналитика: определение источников данных, прототипирование компонентов
- Проектирование: архитектура Vue-компонентов, контракты с бэкендом
- Реализация: разработка табов/аккордеонов на Vue, интеграция с инфоблоками и API
- Тестирование: кросс-браузерное, accessibility, производительность
- Документация: описание компонентов, примеры использования
- Поддержка: гарантия 3 месяца
| Компонент | Ориентировочный срок |
|---|---|
| Табы со статичным контентом + URL-сохранение | 1-2 дня |
| Табы с ленивой загрузкой вкладок | 2-3 дня |
| Аккордеон с анимацией | 1 день |
| Связанные табы + динамические данные (как пример с ценами) | 3-5 дней |
Сроки определяются количеством источников данных, требованиями к анимациям и сложностью интеграции с Битрикс-компонентами. Получите консультацию по вашему проекту — мы подберём оптимальное архитектурное решение.
Закажите разработку табов под ключ — мы подготовим коммерческое предложение за 1 рабочий день. Свяжитесь с нами, чтобы обсудить детали вашего проекта.







