Все презентационные компоненты должны расопологаться в ~components/base Все глобальные стили подключаются в ~assets/scss/_global остальные стили должны лежать в компоненте
- Имя переменной – существительное.
- Имя функции – глагол или начинается с глагола. Бывает, что имена для краткости делают существительными, но глаголы понятнее.
- Имена однофайловых компонентов должны быть всегда в PascalCase
- При использовании компоненты в шаблоне стоит писать в kebab-case например (
html <base-button></base-button>
) - Базовые презентационные компоненты должны начинаться с префикса Base (например, BaseButton)
- Компоненты, которые должны иметь только один активный экземпляр, следует начинать именовать с префикса The (например TheHeader)
- Если компонент имеет смысл только в контексте одного родительского компонента, то это отношение должно быть очевидным в его имени. (Например TodoList, TodoListItem, TodoListItemButton)
- Понятное: в меру детальным, в меру абстрактным
- Короткое: не более 2-3 слов
- Произносимое: чтобы его можно было упомянуть в обсуждении
- Имена компонентов должны состоять из полных слов, а не аббревиатур
В основу мы положим БЭМ. Чтобы не тащить весь стек технологий БЭМа в свои проекты, мы его упростим. Разделитель между блоком и элементом в нотации — одиночный дефис. Разделитель перед модификатором — двойной дефис.
Если блок или модификатор содержат несколько слов — используется кэмел-кейс. При необходимости для обозначения проекта или крупного раздела проекта используется префикс с подчёркиванием.
Написать дефис быстрее, чем подчёркивание. Также написать один дефис проще, чем два.
Поэтому чем чаще используется сущность в названии класса, тем в меньшее количество действий его следует писать. Общие модификаторы — это отдельные классы. Пишутся кэмел-кейсом с префиксом is- без подчёркивания.
- is-disabled — элемент неактивен;
- is-active — активный элемент (текущий пункт меню или строчка в списке);
- is-pressed — нажатый (приоритетнее использовать :active)
- is-focused — в фокусе (приоритетнее — :focus);
- is-hidden — спрятан через display:none;
- is-invisible — спрятан через нулевую непрозрачность;
- is-visible — видимый;
- is-highlighted — выделенный;
- is-animated — анимированный;
- is-animating — анимируется прямо сейчас;
- is-ready-for… — для скриптовых состояний;
- is-big / is-small / is-large… — глобальные размеры блоков с фиксированными ширинами и высотами;
- is-font-regular / is-font-big / is-font-small / is-font-large… — глобальные размеры шрифтов
- is-font-green / is-font-color… — цвет шрифта;
- is-bg-green / is-bg-color… — цвет фона.
Блок шапка: .header
Логотип в шапке, элемент: .header-logo
Логотип может быть также блоком: .header-logo.logo
Шапка с другим фоном: .header--greenBackground
Кнопка в шапке: .header-button.button
Кнопка в шапке, заблокированная. Общий модификатор: .header-button.button.is-disabled
Кнопка в шапке, заблокированная. Модификатор кнопки: .header-button.button.button--disabled
Для форматирования нам потребуется vs code и плагины для vs code vetur, prettier и eslint, конфиг для форматирования лежит в папке с проектом
Для избежания путанницы с путями при импортах используем ~ (обращение к корневой структуре, например '~/components/TheHeader' )
Хотя Vue и поддерживает передачу атрибутов в виде сложных объектов, старайтесь избегать этого. Старайтесь ограничиться простыми типами JavaScript и функциями для этого. Не передавайте сложные объекты в компоненты-наследники.
- Используя для каждого свойства отдельный атрибут - API вашего компонента будет более наглядным.
- Такой подход совместим с API к которому мы все привыкли у нативных HTML(5) элементов.
- Созданые вами атрибуты будет легче понять другим членам команды.
- При передаче сложных объектов сразу не видно, какие из его свойств далее используются, - это затруднит рефакторинг.
- Используйте отдельные атрибуты для каждой опции и передавайте в нее примитив (флаг, строку, число) или функцию.
<!-- правильно -->
<range-slider
:values="[10, 20]"
min="0"
max="100"
step="5"
:on-slide="updateInputs"
:on-end="updateResults">
</range-slider>
<!-- неправильно -->
<range-slider :config="complexConfigObject"></range-slider>
Template -> Script -> Style
Методы components -> props -> data -> computed -> watch -> methods; далее lifecycle methods (created, mounted etc)
<script type="text/javascript">
export default {
// обязательно не забываем имя к.
name: 'RangeSlider',
// можем использовать композицию уже существующих к.
extends: {},
// перечисление свойств и переменных
props: {
bar: {}, // еще лучше если по-алфавиту
foo: {},
fooBar: {},
},
data() {},
computed: {},
// когда внутри используются другие к.
components: {},
// методы
watch: {},
methods: {},
// методы жизненного цикла к.
beforeCreate() {},
mounted() {},
};
</script>
В Vue все инлайн-выражения и методы компонента напрямую относятся к VM (ViewModel) и меняют ее состояние. При декларации собственных событий важно их грамотно называть, чтобы избежать сложности при дальнейшей разработке и использовании компонента.
- Разработчики могут использовать совпадающие имена, что может вызвать проблемы.
- Полная свобода в выборе имён событий может также привести к проблемам с обработкой шаблонов.
- В названиях событий стоит использовать кебаб нотацию kebab-cased.
- Название компонента должно быть уникальным и отражать что в нем происходит, например: upload-success, upload-error или dropzone-upload-success, dropzone-upload-error
- В именах компонентов лучше использовать только существительные и глаголы, например: client-api-load, drive-upload-success
В контексте кода компонента Vue this всегда означает экземпляр самого компонента. Таким образом если вам понадобится обратиться к ней в другом контексте сделайте так, чтобы this означало component. То есть, не используйте устаревшие конструкции присваивания вроде const self = this;. Можно и нужно использовать component в Vue компонентах для этого.
- Присваивая this к переменной названной component напрямую укажет тем кто это будет использовать, что это означает сам компонент.
<script type="text/javascript">
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
console.log(this.hello());
}
}
};
</script>
<!-- неправильно -->
<script type="text/javascript">
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
const self = this; // не нужно
console.log(self.hello());
},
},
};
</script>