Integrating Vue.js with a 1C-Bitrix Site Template
The main challenge of integrating Vue into a Bitrix template is the conflict between the global state of jQuery plugins — which Bitrix uses extensively — and Vue's reactivity system. There is also the issue of script loading order, which Bitrix controls through its own asset manager.
Connecting Vue to the Template Without Conflicts
In the header.php of the Bitrix template, add Vue as a module via the asset manager:
\Bitrix\Main\Page\Asset::getInstance()->addJs('/local/templates/main/vue-dist/app.js', true);
The true flag moves the script to the end of <body>, which is important for Vue since it requires the DOM to be ready.
An alternative is BX.ready(), Bitrix's wrapper around DOMContentLoaded:
BX.ready(function() {
const { createApp } = Vue;
createApp(App).mount('#vue-app');
});
Mount Points in the Template
In Bitrix template files (.php), place div containers for Vue widgets:
// In header.php or wherever needed on the page
<div id="vue-search-widget" data-catalog-id="<?= $catalogId ?>"></div>
The Vue application reads attributes via el.dataset:
const el = document.getElementById('vue-search-widget');
const catalogId = el.dataset.catalogId;
createApp(SearchWidget, { catalogId }).mount(el);
Passing the CSRF Token
Bitrix generates a CSRF token to protect forms. When making AJAX requests from Vue, it must be included:
// Retrieve the token from a cookie (Bitrix stores it in bitrix_sessid)
function getBitrixToken() {
return document.querySelector('input[name="sessid"]')?.value
|| BX.bitrix_sessid?.();
}
// In the axios config:
axios.defaults.headers.common['X-Bitrix-Csrf-Token'] = getBitrixToken();
Conflict with jQuery and BX.UI
Bitrix uses window.BX — its own namespace with utilities — alongside jQuery. Vue does not directly conflict with them, but:
- Do not use jQuery to manipulate the DOM inside Vue components — Vue loses reactivity
-
BX.UI.Dialog,BX.PopupWindow— can be called from Vue viaonMounted/events, but not from the template
Real-World Case
A corporate website on Bitrix: a Vue product-selection widget was added to the template. The widget worked, but after a Bitrix modal window (BX.PopupWindow) was opened, Vue's reactivity broke — the popup cloned the DOM element of the mount point. The solution: mounting the Vue widget to document.body via teleport, rather than inside the element that could be cloned.
Delivery Timelines
Integrating Vue into an existing template with one or two widgets — 4 to 8 hours.







