Полный цикл в digital

Работа с Vue в Битрикс

Битрикс уже содержит в себе фремворк Vue.js, подключается в виде расширения:

<? Bitrix\Main\UI\Extension::load("ui.vue3"); ?>

В битрикс доступны все версии Vue.js, для подключения разных версий, меняется только цифра ui.vue3.

vuex который необходим для организации хранилища, подключается в виде расширения:

<? Bitrix\Main\UI\Extension::load("ui.vue.vuex"); ?>

Режим разработки

Для упрощения кастомизации, необходимо включить режим разработчика, для этого в файле /bitrix/php_interface/init.php или /local/php_interface/init.php надо разместить константу:

define('VUEJS_DEBUG', true);

Сделав это, можно в консоли разработчика увидеть все компоненты Vue и их данные, все исходники минифицированы и без этого будет трудно разобраться в коде.

Расширение для браузера

Для того, чтобы в консоли разработчика появилась информация по Vue в соответствующий вкладке, необходимо установить расширение для браузера, я использую Гугл Хром, переходим в магазин и устанавливаем расширение для браузера.

Просмотр доступных компонентов:

Для просмотра состояния компонентов и их данных, используется вкладка Vuex:

Использование Vue по дефолту

Для использования функций Vue в Битрикс, нужно использовать не Vue.xxx, а BX.Vue.xxx где xxx нужная функция:

script.js// экземпляр Vue
const BitrixVue = BX.Vue3.BitrixVue;
// настройки
const app = BitrixVue.createApp({
    // хранения данных
    data() { },
    // свои функции
    methods: { },
    // вычисляемые свойства
    computed: { },
    // асинхронные действия
    watch: { },
    // повторяющийся код
    mixins: [ ],
});
// контейнер
app.mount('#app');

В template.php разметку делаем как будто мы работаем во Vue файле:

template.php<? Bitrix\Main\UI\Extension::load("ui.vue3"); ?>

<div id="app">
    {{ counter }}
</div>

Соответственно в style.css пишем стили для нашего компонента которые так же подтянутся.

Использование Vue с выносом функций из BX.Vue3 в глобальный объект Window

Если на проекте Vue используется везде, значит есть возможность установить его глобально, условно в header.php сделаем подключение:

header.php<? Bitrix\Main\UI\Extension::load("ui.vue3"); ?>

Теперь наш объект BX.Vue3 есть везде, теперь мы можем подключить другой скрипт глобально:

header.php<script> for (const key in BX.Vue3) window[key] = BX.Vue3[key] </script>

Тут мы просто вынесли функции из BX.Vue3 в window, после этого нам станет доступен «нативный» синтаксис, теперь мы можем переписать свой script.js:

script.jsBX.ready(() => {
    const application = createApp({
        // хранения данных
        data() {
            return {
                name: 'Привет'
            }
        },
        // свои функции
        methods: {},
        // вычисляемые свойства
        computed: {},
        // асинхронные действия
        watch: {},
        // повторяющийся код
        mixins: [],
    });
    application.mount('#root');
})

Рабочий вариант, но все же это плохое решение. Мы засоряем глобальный объект window. Можно еще по желанию удалить из window BX.Vue3, так как все функции мы уже вынесли.

Использование Vue через деструктуризация

Что, если на проекте Vue используется не везде, и нет желания засорять window, но хочется использовать функции Vue без BX.Vue3, выход есть, и причем весьма простой, нужно использовать деструктуризацию:

header.php<? Bitrix\Main\UI\Extension::load("ui.vue3"); ?>
<script>const { createApp } = BX.Vue3</script>
script.jsBX.ready(() => {
    const application = createApp({
        // хранения данных
        data() {
            return {
                name: 'Привет'
            }
        },
        // свои функции
        methods: {},
        // вычисляемые свойства
        computed: {},
        // асинхронные действия
        watch: {},
        // повторяющийся код
        mixins: [],
    });
    application.mount('#root');
})

У нас все так же будет замечательно работать, только теперь данные функции у нас не в объекте window.

Для получения данных с бэка, есть не самый красивый, но рабочий вариант:

template.php<script>
    const arResult = <?=Bitrix\Main\Web\Json::encode($arResult)?>
</script>

Свой компонент с Vue

Создаем с нуля наш компонент.

Создаем template.php с логикой Vue, в данном примере будет добавление пользователя и удаление пользователя:

template.php<? if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); ?>
    <ul id="users-list" class="users-list">
    <li v-for="(user, key) in arResult.users" class="users-list__item" :key="key">
        {{ user }}
        <button type="button" @click="deleteUser(user.id)">Удалить пользователя</button>
    </li>
    <form @submit="addUser" class="form">
        <div class="form__field">
            <label>Имя пользователя</label>
            <input type="text" name="name">
        </div>
        <button type="submit">Добавить нового пользователя</button>
    </form>
</ul>

Немного добавим стилей в style.css, чтобы все убедились что стили работают:

style.css.users-list {
    padding: 12px;
}
.users-list__item {
    padding: 12px;
    background-color: #e2e2e2;
    border-radius: 4px;
    margin-bottom: 8px;
}

Напишем логику в class.php. Тут все просто подключаем наш Vue, далее создаем класс и наследуемся от стандартного CBitrixComponent и реализуем интерфейс чтобы наш класс был контролируемым и мы могли работать с ним через BX.ajax.runComponentAction:

class.php<? if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

use Bitrix\Main\UI\Extension,
    Bitrix\Main\Engine\Contract\Controllerable;

Extension::load("ui.vue3");
class UsersList extends CBitrixComponent implements Controllerable
{
    protected static array $users = [
        [
            'id' => 1,
            'name' => 'Alexander',
        ],
        [
            'id' => 2,
            'name' => 'Ivan',
        ],
        [
            'id' => 3,
            'name' => 'Sergey',
        ],
        [
            'id' => 4,
            'name' => 'Smith',
        ],
        [
            'id' => 5,
            'name' => 'John'
        ],
    ];
    public function configureActions(): array
    {
        return [];
    }

    public function deleteUserAction($id): array
    {
        foreach (self::$users as $key => $user) {
            if ($user['id'] == $id) {
                unset(self::$users[$key]);
                break;
            }
        }
        return self::$users;
    }

    public function getUsersAction(): array
    {
        return self::$users;
    }

    public function addUserAction(): array
    {
        $lastUser = end(self::$users);
        $newUser = [
            'id' => $lastUser['id'] + 1,
            'name' => $_POST['name'],
        ];
        self::$users[] = $newUser;
        return self::$users;
    }

    public function executeComponent(): void
    {
        $this->includeComponentTemplate();
    }
}

Далее все просто, берем создаем наше Vue приложение, создаем нужные нам объекты, переменные, функции и работаем с ними. В самом начале создаем реактивный объект arResult в который будем помещать наши другие массивы, или объекты, данный объект будет отслеживать изменения и менять страницу в соответствии с нашей логикой в template.php:

script.jsconst { runComponentAction } = BX.ajax;
const { ref, createApp, reactive } = BX.Vue3;
BX.ready(() => {
    createApp({
        setup() {
            function deleteUser(id) {
                // нужно правильно указать пространство имен и название компонента
                const request = runComponentAction("my_components:test", "deleteUser", {
                    mode: "class",
                    data: { id: id },
                });
                request.then((reponse) => arResult.users = reponse.data);
            }

            function addUser(e) {
                e.preventDefault();
                // нужно правильно указать пространство имен и название компонента
                const request = runComponentAction("my_components:test", "addUser", {
                    mode: "class",
                    data: new FormData(e.target),
                });
                request.then((reponse) => arResult.users = reponse.data);
            };

            const arResult = reactive({});
            // нужно правильно указать пространство имен и название компонента
            const request = runComponentAction("my_components:test", "getUsers", {
                mode: "class",
            });
            request.then((reponse) => (arResult.users = reponse.data));

            return {
                arResult,
                addUser,
                deleteUser
            };
        },
    }).mount("#users-list");
});
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!