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

SPA на Vue в Bitrix

Мы будем делать SPA на Vue используя расшерения (extensions) и сборщик CLI. Кому этот вариант не подходить, может внутри поставить свой Vue, и уже без Bitrix CLI собирать свое приложение, а потом в config.php указать путь к собранному бандлу.

Простое приложение

Вызовим расширение на любой странице:

test/index.php<? require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php"); ?>

<?php \Bitrix\Main\UI\Extension::load(['hmarketing.vue']); ?>

<div id="root"></div>

<? require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/footer.php"); ?>

Для создания SPA на Vue, сначала нужно импортировать Vue:

/local/js/hmarketing/vue/src/scripts.jsimport { createApp } from "ui.vue3";

Логика импортов тут точно такая же как при подключении расширения. При сборке наш config.php дополниться нужными зависимостями автоматически.

Напишем для начала простое приложение без компонентов:

/local/js/hmarketing/vue/src/scripts.jsimport { createApp } from "ui.vue3";

document.addEventListener("DOMContentLoaded", () => {
  createApp({
    data() {
      return {
        counter: 1,
      };
    },
    mounted() {
      setInterval(() => {
        this.counter++;
      }, 1000);
    },
    template: `
{{ counter }}
`, }).mount("#root"); });

Далее вынесем это все в компонент и добавим метод reset:

/local/js/hmarketing/vue/src/scripts.jsimport { createApp } from "ui.vue3";
import App from "./components/App";
document.addEventListener("DOMContentLoaded", () => {
    createApp(App).mount("#root");
});
/local/js/hmarketing/vue/src/components/App.vueexport default {
    data() {
        return {
            count: 0,
        };
    },
    name: "Counter",
    methods: {
        reset() {
            this.count = 0;
        },
    },
    mounted() {
        setInterval(() => this.count++, 300);
    },
    template: `
    <div>
      <button class="button-counter" @click="reset">reset count</button>
      counter : {{ count }}
    </div>
  `,
};

Приложение с роутингом и компонентами

SPA на Vue для Bitrix с использованием Bitrix CLI, в приложении есть возможность использовать JS от Bitrix, мы можем так же использовать аяксы к компонентам, модулям, и прочим библиотекам Битрикс.

Готовый код можно скачать в моем репозитории на GitFlic.

Структура расширения (extensions):

  • vue основная папка расширения
  • dist файлы сборки после Bitrix CLI
      • App.js основной компонент с роутингом
      • Counter.js компонент с счетчиком
      • About.js страница о компании
      • Workers.js страница работников
    • scripts.js основной файл скртптов расширения
    • styles.scss основной файл стилей расширения
  • bundle.config.js
  • config.php
/local/js/hmarketing/vue/src/components/App.jsimport About from "../pages/About";
import Workers from "../pages/Workers";

export default {
    components: { About, Workers },
    template: `<div>
        <nav>
            <ul>
                <li><router-link to="/">Main</router-link></li>
                <li><router-link to="/workers">Workers</router-link></li>
                <li><router-link to="/about">About</router-link></li>
            </ul>
        </nav>
        <main>
            <router-view />
        </main>
    </div>`,
};
/local/js/hmarketing/vue/src/components/Counter.jsexport default {
    data() {
        return {
            count: 0,
        };
    },
    name: "Counter",
    methods: {
        reset() {
            this.count = 0;
        },
    },
    mounted() {
        setInterval(() => this.count++, 300);
    },
    template: `
    <div>
      <button class="button-counter" @click="reset">reset count</button>
      counter : {{ count }}
    </div>
  `,
};
/local/js/hmarketing/vue/src/pages/About.jsimport Counter from "../components/Counter";
export default {
    data() {
        return {
            name: "Страница о компании",
        };
    },
    name: "About",
    components: {
        Counter,
    },
    template: `
    <div>
        <h1>{{ name }}</h1>
        <Counter/>
    </div>
  `,
};
/local/js/hmarketing/vue/src/pages/Workers.jsexport default {
    data() {
        return {
            name: "Страница работников",
        };
    },
    name: "Workers",
    template: `
    <div>
      <h1>{{ name }}</h1>
    </div>
  `,
};
/local/js/hmarketing/vue/src/scripts.jsimport './styles.scss';
import { createApp } from "ui.vue3";
import { createRouter, createWebHashHistory } from "ui.vue3.router";
import Workers from "./pages/Workers";
import About from "./pages/About";
import App from "./components/App";
const router = createRouter({
    routes: [
        {
            path: "/workers",
            component: Workers,
        },
        {
            path: "/about",
            component: About,
        },
    ],
    history: createWebHashHistory(),
});
document.addEventListener("DOMContentLoaded", () => {
    createApp(App).use(router).mount("#root");
});
/local/js/hmarketing/vue/src/styles.scss.button-counter {
  display: inline-block;
  box-sizing: border-box;
  padding: 0 16px;
  margin: 0 15px 15px 0;
  outline: none;
  border: none;
  border-radius: 4px;
  height: 30px;
  line-height: 30px;
  font-size: 12.5px;
  font-weight: normal;
  text-decoration: none;
  vertical-align: top;
  color: #55677d;
  background-color: #dfe6ed;
  cursor: pointer;
  user-select: none;
  appearance: none;
  touch-action: manipulation;
  overflow: hidden;

  &:focus-visible {
    box-shadow: 0 0 0 3px lightskyblue;
  }

  &:hover {
    opacity: 0.88;
  }

  &:active {
    line-height: 32px;
  }

  &:disabled {
    pointer-events: none;
    opacity: 0.65;
  }
}
/local/js/hmarketing/vue/bundle.config.jsmodule.exports = {
    input: "./src/scripts.js",
    output: {
        js: "./dist/script.bundle.js",
        css: "./dist/style.bundle.css",
    },
    namespace: 'BX.HM',
    browserslist: true,
    plugins: {
        resolve: true,
    }
};
/local/js/hmarketing/vue/config.php<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
return [
    'css' => './dist/style.bundle.css',
    'js' => './dist/script.bundle.js',
    'rel' => [
		'main.polyfill.core',
		'ui.vue3',
		'ui.vue3.router',
	],
	'skip_core' => true,
];
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!