Приведенные ниже правила нужны для соблюдения консистентности кода. Соблюдение этих правил приветствуется.
- Все папки должны быть названы в
camelCase
👎
components/
|- main-header ...
|- LeadComponent ...
|- projects_section ...
// Это директории
👍
components/
|- mainHeader ...
|- leadComponent ...
|- projectsSection ...
// Это директории
- Изображения
- Все изображения должны быть описательными и в
kebab-case. - Структура названия:
название-модификатор.расширение - Все изображение должны быть форматированы в
.webp
👎
images/
|- photoOfficeXl.webp
|- bgWhite.jpg
|- bg_black.webp
|- ValuablePhoto375.png
👍
images/
|- photo-office-xl.webp
|- background-main-white.webp
|- background-main-black.webp
|- valuable-photo-375.webp
- Иконки
- Названия иконок должны быть описательными, в
camelCaseи оканчиваться на 'Icon' - Структура названия:
названиеIcon.svg
👎
icons/
|- icon-telegram.svg
|- bnmap_logo_icon.svg
|- background.svg
👍
icons/
|- iconTelegramIcon.svg
|- bnmapLogoIcon.svg
|- dottedBackgroundIcon.svg
- Размер отступа должен быть равен двум символам;
- Не следует опускать скобки и писать без перехода на новую строку функции, циклы, классы и др.
// 👎
if(condition) doSomething();
while(condition) iterating++;
for(var i=0;i<100;i++) someIterativeFunction();
// 👍
if ( condition ) {
...
}
while ( condition ) {
...
}
for ( var i = 0; i < 100; i++ ) {
...
}- Кавычки должны быть одинарными
'
let variable = 'hello'- Условные проверки:
// При проверке длины массивы
// 👎
if ( array.length > 0 ) ...
// 👍
if ( array.length ) ...
// При проверке массива на пустоту
// 👎
if ( array.length === 0 ) ...
// 👍
if ( !array.length ) ...
// При проверке на не пустую строку
// 👎
if ( string !== "" ) ...
// 👍
if ( string ) ...
// При проверке пустой строки
// 👎
if ( string === "" ) ...
// 👍
if ( !string ) ...
Аналогично:
// 👎
if ( foo === true ) ...
// 👍
if ( foo ) ...
// 👎
if ( foo === false ) ...
// 👍
if ( !foo ) ...
// Однако если нужна проверка только на `Boolean` значение то использовать:
if ( foo === false ) ...- Следует избегать лишних приведений к типу
Boolean
// 👎
const result = true
if (!!result) {
...
}
// 👍
const result = true
if (result) {
...
}- Названия переменнных, функций, параметров и др.
- Все переменные, функции и параметры должны быть именованы в
camelCase
// 👎
let SomeVariable
let some_variable
// 👍
let someVariable- Все переменные, функции, параметры, и классы должны иметь осмысленное название, которое отражает суть названной сущности
// 👎
function getFromLS(value) ...
// 👍
function getItemFromLocalStorage(itemKey) ...
// 👎
let r = 'Moscow'
// 👍
let region = 'Moscow'- Для дефолтных переменных следует использовать
CONSTANT_CASE(upper snake case)
const DEFAULT_REGION = 'Moscow'- Всегда использовать ранний
return, это улучшает читаемость и скорость выполнения кода
// 👎
function returnLate(foo) {
var ret;
if ( foo ) {
ret = "foo";
} else {
ret = "quux";
}
return ret;
}
// 👍
function returnEarly(foo) {
if ( foo ) {
return "foo";
}
return "quux";
}- Перед последним
returnвсегда долженр быть отступ
// 👎
function someFucntion() {
const someVariable = 'hello'
return someVariable
}
// 👍
function someFucntion() {
const someVariable = 'hello'
return someVariable
}- Всегда использовать
===вместо==для сраввнения
// 👎
if (variable == 'hello') ...
// 👍
if (variable === 'hello') ...- При наличии у функции более двух параметров передавать их как объект
// 👎
function manyParametersFunction(name, phone, address) { ... }
manyParametersFunction('Viktor', '+79993334444', 'Moscow')
// 👍
function manyParametersFunction({ name, phone, address }) { ... }
manyParametersFunction({ name: 'Viktor', phone: '+79993334444', address: 'Moscow' })- Коментарии
- Количество комментариев необходимо свести к минимуму за счет построения понятной структуры кода и грамотного именования сущностей
- При комментировании костылей необходимо выделять их в отдельный блок и добавлять отступы до и после блока
someFunction()
// Костыль. <Причина появления костыля>
someClutchFunction();
// ----
someFunction()- Конкантенация строк
// 👎
let someString = someString1 + ' ' + someString2
// 👍
let someString = `${someString1} ${someString2}`- Выбрасывать (
throw) только объектError
// 👎
throw 'error'
// 👍
throw new Error('error')- Не использовать тернарный опетор при наличии более простой альтернативы
// 👎
let score = val ? val : 0
// 👍
let score = val || 0- Документация
JSDocстрого на английском языке. Это связано с тем, что английский более строгий язык и допускает меньше двойных трактований
// 👎
/**
* Возвращает сумму двух чисел
* ...
*/
function add(x, y) {
return x + y;
}
// 👍
/**
* Returns sum of two numbers
* ...
*/
function add(x, y) {
return x + y;
}- Использовать
@typedefвJSDocдля повторяющихся типов
// 👎
/**
* @param {Object} user
* @param {string} user.name
* @param {number} user.age
*/
function greetUser({ name, age }) {
console.log(`Привет, ${user.name}!`);
}
/**
* @param {Object} employee
* @param {string} employee.name
* @param {number} employee.age
*/
function hireEmployee({ name, age }) {
console.log(`${employee.name} принят на работу.`);
}
// 👍
/**
* @typedef {Object} Person
* @property {string} name
* @property {number} age
*/
/**
* @param {Person} user
*/
function greetUser({ name, age }) {
console.log(`Привет, ${user.name}!`);
}
/**
* @param {Person} employee
*/
function hireEmployee({ name, age }) {
console.log(`${employee.name} принят на работу.`);
}- При использование
JSDocне следует добавлять отступ после описания
// 👎
/**
* Returns sum of two numbers
*
* @param {number} x
* ...
*/
function add(x, y) {
return x + y;
}
// 👍
/**
* Returns sum of two numbers
* @param {number} x
* ...
*/
function add(x, y) {
return x + y;
}- Для типизации объектов следует использовать
Type
// 👎
interface ComplexObject {
id: number;
name: string;
data: any[];
}
// 👍
type ComplexObject = {
id: number;
name: string;
data: any[];
};- Используя
typescriptне следует типизировать код с помощьюJSDoc
// 👎
/**
* Returns sum of two numbers
* @param {number} x
* @param {number} y
* @returns {number}
*/
function add(x: number, y: number): number {
return x + y;
}
// 👍
/**
* Returns sum of two numbers
*/
function add(x: number, y: number): number {
return x + y;
}- Название компонентов
- Названия компонентов всегда в
PascalCase
👎
components/
|- myComponent.vue
👍
components/
|- MyComponent.vue
- Названия компонентов должны содержать более одного слова. Сокращения не допускаются
// 👎
<Lead />
// 👍
<LeadBanner />- Названия базовых компонентов начинаются с Base
👎
components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue
👍
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
- Тесно связанные компоненты должны содержать название компонента родителя
👎
components/
|- TodoList.vue
|- TodoItem.vue
|- TodoButton.vue
components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue
👍
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
- Порядок слов в названиях компонентов от высших (наиболее общих) к низшим (модификаторам)
👎
components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue
👍
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
- Кастомные компоненты в
<template>должны быть вPascalCase. Сторонние компоненты вkebab-case
// 👎
<BaseButton />
<NSidebar />
// 👍
<BaseButton />
<n-sidebar />- Пропсы
- Названия пропсов в
<template>всегда вkebab-case, в<script>—camelCase
// 👍
<template>
<ChildComponent :title-tag='h1' />
</template>
<script>
const props = defineProps({
titleTag: String
})
</script>- Детализированное описание пропсов используется всегда
// 👎, разрешается только при прототипировании
const props = defineProps(['status'])
// 👍
const props = defineProps({
status: {
type: String,
required: true,
}
})- Простые выражение в
<template>
// 👎
{{
fullName.split(' ').map((word) => {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}}
// 👍
{{ normalizedFullName }}- Порядок элементов для
SFCкомпонентов:template -> script -> style
// 👎
<style>/* ... */</style>
<script>/* ... */</script>
<template>...</template>
// 👍
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>- Селекторов тэгов не должно быть в
<style scoped>
// 👎
<template>
<button>×</button>
</template>
<style scoped>
button {
background-color: red;
}
</style>
// 👍
<template>
<button class="btn btn-close">×</button>
</template>
<style scoped>
.btn-close {
background-color: red;
}
</style>- В качестве блока родителя в названии класса элемента следует использовать название класса родителя. Если такой вариант не выглядит хорошо — следует разбить компонент на подкомпоненты
- Переход от компонента родителя в названии блока класса к компоненту ребенка показан в примере
class="items__item item"
// 👍
<template>
<section class="items">
<h2 class="items__title" />
<div class="items__list">
// item можно вынести в отдельный компонент
<div
v-for="(item, index) in items"
:key="index"
class="items__item item"
>
<p class="item__text" />
</div>
</div>
<div class="items__footer>
<div class="items__copyright" />
<img class="items__footer-image />
</div>
</section>
</template>- В названии класса не должно быть типа
// 👎
<div class="items-list">
<div class="items-list__item item">
<div class="items-list__item item">
<div class="items-list__item item">
<div class="items-list__item item">
</div>
// 👍
<div class="items">
<div class="items__item item">
<div class="items__item item">
<div class="items__item item">
<div class="items__item item">
</div>