Если мы говорим о разработке приложения на Vue.js, то web-страница представляет собой взаимодействующие между собой компоненты. Компонент - переиспользуемый экземпляр Vue, имеющий название (https://ru.vuejs.org/v2/guide/components.html). Это специальная абстракция, позволяющая собрать приложение из небольших кусочков, представляющих из себя древовидную структуру. Любой компонент можно переиспользовать (в том числе, рекурсивно).
Поскольку в нашем проекте встречаются компоненты различного назначения, следует уточнить терминологию:
1. Компоненты, выделенные отдельно внутри каталога gemosystem/frontend/components для удобства последующего переиспользования. Их имеют ввиду, когда говорят "компоненты". Среди них есть "чистые" компоненты, начинающиеся с "Base..." (см. "Именование базовых компонентов").
3. Компоненты, созданные для отрисовки тех или иных страниц, или частей страниц. Называются views, "вьюхи" (gemosystem/frontend/views)
4. Компоненты, созданные для управление состоянием приложения: gemosystem/frontend/store. Их имеют ввиду, когда говорят о Vuex, хранилище, мутациях и экшенах.
Vuex - паттерн общего хранилища состояний приложения. Обычно состоит из 3-х базовых категорий: Actions, Mutations и States (https://vuex.vuejs.org/ru/).
Важно следить за соблюдением этого принципа, не пытаться обратиться и поменять свойства компонента или содержимое страницы "грязным" способом, обращаясь напрямую к DOM или используя другие JS-фреймворки.

Принято решение (начало 2018г) о плавном переносе всего функционала ГС на архитектуру SPA (PHP бэк + Vue.js фронт). На момент принятия решения в проекте уже использовались компоненты Vue.js (как предварительно собранный webpack-ом скрипт, так и подгрузка vue.js как внешнего скрипта). Весь этот код подлежит рефакторингу, переносу функционала в виде новых компонентов SPA-приложения. Его структура и функционал вне рамок этой статьи.
При разработке и ревью предлагается следовать официальным рекомендациям от разработчиков Vue.js https://ru.vuejs.org/v2/style-guide/article/1
https://github.com/vuejs/vuex/tree/dev/examples
https://itnext.io/how-to-structure-a-vue-js-project-29e4ddc1aeeb
/frontend // корневой каталог для фронта.
/components // каталог для компонентов. Тут хранятся только файлы *.vue (как правило, однофайловые).
/src // для случая, когда компонент оказывается большим, он дробится на html-, js- и scss-составляющие, которые помещаются сюда в подкаталог с соответствующим названием
/TheMainLayout // каталог содержит встраиваемые в TheMainLayout.vue файлы
script.js // js-составляющая, всегда имеет название script.js
style.scss // scss-составляющая, всегда имеет название style.scss
template.html // html-составляющая, всегда имеет название template.html
/User // группа логически связанных компонентов объединяется в один подкаталог
/src // внутри группы компонентов так же может присутствовать каталог src для компонентов, требующих разделения на составляющие. Принцип расположения файлов идентичен указанному выше.
Info.vue
NameLabel.vue
Photo.vue
BaseAlert.vue // однофайловый "чистый" компонент (подробнее о том, что это в статье "Именование базовых компонентов" у официалов)
BaseAvatar.vue
SideBar.vue
TheMainLayout.vue // компонент, всегда присутствующий в единственном экземпляре на странице
/resource // каталог ресурсов, созданных и поддерживаемых вне фреймворка Vue
/Bootstrap // корпоративный стиль для Bootstrap 4
/Theme
/Main
bootstrap.scss
/store // каталог для модулей, описывающих хранилища состояний
Auth.js // дополнительный модуль хранилища состояний
Main.js // основное хранилище состояний, в котором подключаются дополнительные модули
/views // Файлы представлений. Обычно соотносятся со страницами приложения.
/shift // каталог представлений бизнес-модуля (в данном случае - кассовая смена)
/open // логическая часть модуля (открытие кассовой смены)
CurrentWorkshift.vue // отдельная страница (текущая кассовая смена)
Api.js // компонент для взаимодействия с Api.
App.js // главный файл (точка входа) приложения, в котором происходит монтирование в DOM
AppConfig.js // настройки приложения
Routes.js // динамический роутинг. Определяет зависимость адресной строки браузера и загружаемых модулей.
/www // домашний каталог веб-сервера
/Resource // ресурсы, доступные для загрузки браузером
/App // базовый каталог для сборки всех модулей приложения
Shift.js // файл сборки. Генерируется автоматически сборщиком webpack.
Если ваш функционал может стать частью SPA-приложения (web-страница была или будет целиком создана на Vue.js в рамках описанной здесь архитектуры), то компонент следует создавать и помещать в проект согласно логике, описанной в этой статье.
Если вы стремитесь добавить новый функционал рядом со старым кодом, заставить Vue.js взаимодействовать с jQuery или другим кодом на странице - имейте ввиду, что ваш код в последствии будет переписан вместе с переносом всей логики в новый модуль SPA-приложения. В этом случае, размещайте Vue-компонент рядом с вашим PHP-сервисом, добавляйте его в Webpack для сборки отдельным файлом, который потом подгрузите в старый код (пример: gemosystem/src/Report/Service/Detail).
Обычно компонент состоит из 3 частей
Эти части рекомендуется располагать в одном файле, однако при большом количестве кода стоит разбить файл на 3 с соответствующими расширениями, и поместить их в каталог ./src/{ComponentName}/.
Также Code Style требует придерживаться всегда одинакового порядка указания этих трех частей, поэтому мы всегда указываем в порядке template - script - style.
Мы в команде также стремимся придерживаться правила делать комментарии в верхней части Vue-файла о назначении компонента и (не обязательно) его явных зависимостях (к примеру, от геттеров хранилища, или от событий другого компонента)
Заключен в обрамляющий тэг <template> и должен иметь только один корневой элемент.
Подробнее https://ru.vuejs.org/v2/guide/syntax.html
<template>
<div class="recount-form">
<!-- Официальный Code Style допускает наименования и в CamelCase, но предлагает использовать kebab-case, если он используется всегда. Мы за единообразие,
поэтому у нас принято указывать в шаблонах Vue-компоненты так, как показано ниже -->
<other-component
:prop-1="{a:'1', b:'2'}"
@explode="method1"
></other-component>
<!-- Вот так именовать плохо: официалы запрещают использовать аббревиатуры, а мы - CamelCase -->
<SPComponent></SPComponent>
<!-- Тоже плохо: комплексное условие в v-if следует вынести в отдельное вычисляемое свойство -->
<x-report v-if="loading === false && state !== CLOSED && printerState === SUCCESS"></x-report>
<!-- Смешивать сокращенные и полные директивы - плохо, для единообразия используем директивы с префиксом "v-" -->
<report :short-directive="value" v-on:full-directive="onEvent"></report>
</div>
</template>
Обращаем внимание на порядок опций копонента.
'use strict';
import './OtherComponent.vue'; // импорт нужных компонентов/модулей и пр.
import ...;
// рекомендуется соблюдать порядок опций компонента
export default {
// глобальные опции
name: 'Abc',
// зависимости
components: {
// дочерние компоненты (требуется их импорт)
OtherComponent, ...
},
// интерфейс компонента
props: {
// входные параметры, требуется всегда указывать их тип и по возможности валидировать
id: {
type: String,
default: 'alert-message'
},
...
},
// локальное состояние
data: function() {
// приватные свойства, используемые внутри компонента, представлены в виде функции
return {
...
}
},
computed: {
// вычисляемые свойства
...
}
// события
mounted: function() {
// метод, срабатывающий при монтировании компонента (своего рода, конструктор)
...
},
destroyed: function() {
...
},
// нереактивные свойства
methods: {
// методы компонента
method1: function() {
this.$emit('some event', {someData:{...}}); // инициирование события и передача его родителю (так делать с осторожностью, лучше общаться через хранилище)
}
},
// отрисовка
template: '<pre></pre>'
}
Можно использовать как обычный CSS, так и SASS (https://sass-scss.ru/).
В первом случае:
<style scoped>
.component .class p {
color: #cba034;
}
</style>
Во втором случае:
<style lang="scss" scoped>
.component {
.class {
p {
color: #cba034;
}
}
}
</style>
Кроме того, у нас используется Bootstrap 4 с помощью импорта npm-пакета (достаточно сделать это 1 раз в приложении, чтобы получить стили фреймворка)
import bootstrap from 'bootstrap';
Так же можно подключить файл с темой на основе корпоративного стиля (или любой другой вспомогательный файл стилей) следующими способами:
<!-- Предпочтительный вариант -->
<style type="text/scss" lang="scss" src="frontend/resource/Bootstrap/Theme/Main/bootstrap.scss"></style>
<!-- Обычный CSS -->
<link rel="stylesheet" href="/Resource/Bootstrap/Theme/Main/bootstrap.theme.css" />
<!-- Внутри блока с SCSS-кодом -->
<style lang="scss">
@import 'frontend/resource/Bootstrap/Theme/Main/bootstrap.scss';
</style>
<!-- Внутри блока с JS-кодом -->
<script>
import 'frontend/resource/Bootstrap/Theme/Main/bootstrap.scss';
</script>
Комментарии
Комментариев пока нет.