Перейти к содержимому

BitrixVue 3 - реактивные интерфейсы в 1С-Битрикс

BitrixVue - тонкая обёртка над Vue 3, которая решает специфические для платформы задачи: централизованную версию библиотеки, изоляцию от глобальной области, локализацию и возможность кастомизировать чужие компоненты без правки исходников.

Как это работает

Это Vue 3 с добавками, а не своя библиотека. Поведение Vue не меняется. Добавляются: единая версия для всех модулей, отсутствие Vue в глобальной области, интеграция с локализацией и динамической загрузкой компонентов, механизмы кастомизации. Ограничения тоже есть: нет серверного рендеринга и однофайловых компонентов.

Запуск в двух режимах. В собираемом коде обёртку импортируют и создают приложение обычным способом. На обычной PHP-странице без сборки загружают расширение и обращаются к обёртке через глобальный объект. Монтировать нужно после готовности DOM.

Компоненты бывают классические и мутабельные. Классический - обычный Vue-объект для внутренних задач. Мутабельный нужен, когда решение будут кастомизировать третьи стороны: его можно менять и клонировать, не трогая исходники. Классический объект напрямую мутировать нельзя - только клонировать.

Мутация и клонирование. Мутация меняет компонент до создания экземпляров: на уже отрисованные объекты и на клоны она не действует. Внутри мутации к оригинальным частям обращаются через специальные префиксы - к родительскому шаблону, методам, наблюдателям и данным. Клонирование всегда работает от оригинала.

Объект $Bitrix - мост к платформе. Внутри компонентов доступны локализация, события уровня приложения, глобальные данные, проброс контекста контроллера и клиенты REST и Pull.

Три уровня событий. Компонентный - штатные события Vue на один уровень вверх. Уровень приложения - между частями одного приложения. Уровень сайта - общая шина между разными Vue-приложениями и интерфейсами платформы. Глобальный механизм событий из второй версии больше не поддерживается.

Примеры

1. Запуск приложения

import { BitrixVue } from 'ui.vue3';
const application = BitrixVue.createApp({
data() {
return { items: [] };
},
template: `
<div class="my-app">
<div v-for="item in items" :key="item.id">{{ item.title }}</div>
</div>
`,
});
application.mount('#application-inner');
// без сборки, прямо на странице
\Bitrix\Main\UI\Extension::load('ui.vue3');

Важная деталь монтирования: Vue заменяет узел целиком. Если смонтировать приложение прямо на корневой элемент, этот элемент исчезнет. Поэтому внутри корневого контейнера создают вложенный элемент и монтируют на него.

2. Мутабельный компонент и его кастомизация

BitrixVue.mutableComponent('mymodule-item-card', {
props: ['item'],
template: `<div class="card">{{ item.title }}</div>`,
});
// кастомизация без правки исходника - до создания экземпляров
BitrixVue.mutateComponent('mymodule-item-card', {
template: `<div class="card card--custom">#PARENT_TEMPLATE#</div>`,
methods: {
onClick() {
this.parentOnClick();
trackAnalytics();
},
},
});
// клонирование - всегда от оригинала
const clone = BitrixVue.cloneComponent('mymodule-item-card', 'my-card-clone', {
// изменения клона
});

Именно ради этого механизма компоненты, предназначенные для сторонней доработки, объявляют мутабельными: партнёр меняет поведение, не форкая ваш код.

3. Локализация и события

export const MyComponent = {
computed: {
phrases() {
return this.$Bitrix.Loc.getFilteredPhrases('MYMODULE_CARD_');
},
},
methods: {
notify() {
this.$Bitrix.eventEmitter.emit('MyModule:Item:selected', { id: this.item.id });
},
},
template: `<button @click="notify">{{ phrases.MYMODULE_CARD_SELECT }}</button>`,
};

Вынос фраз в вычисляемое свойство - не украшательство: массовые обращения к локализации прямо в шаблоне заметно нагружают перерисовку.

Для связи с другими интерфейсами страницы используют шину уровня сайта из ядра.

Справочник API

APIНазначениеОсобенности
ui.vue3расширение BitrixVueтребует модуль интерфейсов актуальной версии
BitrixVue.createApp() / mount()запуск приложениямонтировать после готовности DOM
BitrixVue.mutableComponent()мутабельный компонентдля решений, которые будут кастомизировать
BitrixVue.mutateComponent()изменение компонентатолько до создания экземпляров
BitrixVue.cloneComponent()клонированиевсегда от оригинала, работает и с классическими
префиксы в мутацияхдоступ к оригиналуродительский шаблон, методы, наблюдатели, данные
$Bitrix.Locлокализацияесть выборка фраз по префиксу
$Bitrix.eventEmitterсобытия приложениямежду частями одного приложения
$Bitrix.Dataглобальные данные приложения
$Bitrix.Applicationконтекст контроллера
$Bitrix.RestClient / PullClientREST и Pullна внешних ресурсах клиент задают явно
EventEmitter из ядрасобытия уровня сайтасвязь с другими приложениями и интерфейсами

Частые ошибки

Мутация не подействовала. Она применяется только до создания экземпляров и не влияет на клоны. Регистрируйте её раньше, а клоны настраивайте отдельно.

Мутация классического компонента не работает. Такие компоненты можно только клонировать.

Клонирование по имени до загрузки оригинала. Результат будет некорректным - сначала загрузите исходный компонент.

Корневой узел исчез после монтирования. Vue заменяет узел целиком - монтируйте на вложенный элемент.

REST и Pull не работают на внешнем ресурсе. Клиент нужно задать явно, иначе внешний виджет не свяжется с порталом.

Локализация тормозит перерисовку. Массовые обращения к фразам прямо в шаблоне дороги - выносите их в вычисляемое свойство.

Используют события из второй версии. Глобальный механизм событий не поддерживается, вместо него три уровня событий.

Частые вопросы

Чем BitrixVue отличается от обычного Vue 3?

Это тот же Vue 3 плюс решения специфических для платформы проблем: единая версия библиотеки для всех модулей (нет конфликтов), отсутствие Vue в глобальной области, встроенная локализация и события, а главное - возможность кастомизировать чужие компоненты мутацией и клонированием без правки исходников. Из ограничений: нет серверного рендеринга и однофайловых компонентов.

Когда объявлять компонент мутабельным?

Когда его будут дорабатывать третьи стороны - партнёры, интеграторы, другие команды. Мутабельный компонент можно изменить и клонировать снаружи, не форкая код. Для внутренних задач достаточно классического Vue-объекта: он проще и его тоже можно клонировать, просто не мутировать.

Как связать Vue-приложение с остальной страницей?

Через уровни событий. Внутри приложения - штатные события Vue и эмиттер уровня приложения из объекта платформы. Между разными Vue-приложениями и обычными интерфейсами - общая шина событий из ядра. Она же связывает ваше приложение с системными интерфейсами, которые Vue не используют.

Почему после монтирования пропал контейнер?

Потому что Vue заменяет узел монтирования целиком - это стандартное поведение библиотеки. Решение простое: внутри вашего контейнера создайте вложенный элемент и монтируйте приложение на него. Тогда внешний контейнер сохранится и его можно переиспользовать.

Связанные темы

Первоисточники