
Aitarget Codestyle
Оглавление
Jade
Классы и идентификаторы
Классы и идентификаторы пишутся в аттрибутах, а не в начале. Это позволяет улучшить читаемость и сохранить однообразие кода.
/* Плохо */
.carousel
nav.nav.nav_pos_left
#carousel
/* Хорошо */
div(class='carousel' id="carousel")
nav(class='nav nav_pos_left')
div(id="carousel")
Несколько аттрибутов
Для нескольких атрибутов запятая не нужна.
/* Плохо */
input.input-text(type='text', name='project', value='csssr', required)
/* Хорошо */
input.input-text(type='text' name='project' value='csssr' required)
Кавычки
Используйте двойные кавычки для текстовых значений.
/* Плохо */
input.input-text(type='text' name='project' value='csssr' required)
/* Хорошо */
input.input-text(type="text" name="project" value="csssr" required)
Необязательные аттрибуты
Не давайте необязательные значения атрибутам.
/* Плохо */
input.input-checkbox(type='checkbox' name='browser[]' value='chrome' checked='checked')
/* Хорошо */
input.input-checkbox(type='checkbox' name='browser[]' value='chrome' checked)
Одиночные аттрибуты
Распологайте одиночные атрибуты в последнюю очередь.
/* Плохо */
input.input-checkbox(type='checkbox' checked name='browser[]' value='chrome')
/* Хорошо */
input.input-checkbox(type='checkbox' name='browser[]' value='chrome' checked)
Длинные строки
Переносите атрибуты новую строку, если их много и/или значения длинные.
/* Плохо */
input.input-text(type='text' name='project' value='csssr' data-required='Это поле обязательно для заполнения!' data-hint='Допустимы только символы латинского алфавита `[a-z-A-Z]` и числа `[0-9]`.' required)
/* Хорошо */
input.input-text(
type='text'
name='project'
value='csssr'
data-required='Это поле обязательно для заполнения!'
data-hint='Допустимы только символы латинского алфавита `[a-z-A-Z]` и числа `[0-9]`.'
required
)
Перенос строки для однотипных блоков
Добавляйте перенос строки для однотипных блоков с множественным вложением элементов.
/* Плохо */
.project
.project__name Lorem
.project__desc
| Lorem ipsum dolor sit amet, consectetur adipisicing elit.
| Unde doloremque neque facilis sed repudiandae tempore ipsum provident officia eaque quas.
.project
.project__name Ipsum.
.project__desc
| Lorem ipsum dolor sit amet, consectetur adipisicing elit.
| Unde doloremque neque facilis sed repudiandae tempore ipsum provident officia eaque quas.
/* Хорошо */
.project
.project__name Lorem
.project__desc
| Lorem ipsum dolor sit amet, consectetur adipisicing elit.
| Unde doloremque neque facilis sed repudiandae tempore ipsum provident officia eaque quas.
.project
.project__name Ipsum.
.project__desc
| Lorem ipsum dolor sit amet, consectetur adipisicing elit.
| Unde doloremque neque facilis sed repudiandae tempore ipsum provident officia eaque quas.
Строчные элементы
Строчные элементы можно записывать на одной строке через двоеточие :.
злоупотреблять с длинными классами.
/* Хорошо */
ul.nav
li.nav__item
a.nav__link(href='http://aitarget.github.io/') Главная
li.nav__item
a.nav__link(href='http://aitarget.github.io/projects') Проекты
li.nav__item
a.nav__link(href='http://aitarget.github.io/contacts') Контакты
/* Лучше */
ul.nav
li.nav__item: a.nav__link(href='http://aitarget.github.io/') Главная
li.nav__item: a.nav__link(href='http://aitarget.github.io/projects') Проекты
li.nav__item: a.nav__link(href='http://aitarget.github.io/contacts') Контакты
Комментарии
Комментарии в Jade, которые не должны попасть в HTML записываются через //-
Простые или условные комментарии можно записывать прямо в HTML-формате.
// Этот комментарий попадёт в HTML.
//- Этот комментарий не попадёт в HTML.
<!--[if IE]>
meta(name='imagetoolbar' content='no')
meta(name='msthemecompatible' content='no')
<![endif]-->
<!--noindex-->
Это содержимое не будет индексироваться поисковиком.
<!--/noindex-->
Подключение шаблонов
- include header - используется для подключения частиц страницы, например, для шапок и подвалов.
- extends partials/default - используется для внедрения контент в расширяемый шаблон.
- block content - используется для добавления строк кода в определённое место
Во всех случаях через пробел указывается путь от текущего расположения до шаблона без расширения .jade.
Полезные ссылки
jade-lang.com - Документация Jade
http://jsman.ru/jade - Ещё одна документация Jade
http://naltatis.github.io/jade-syntax-docs - Ещё одна документация Jade
html2jade.org - конвертация HTML в Jade и Jade в HTML
Stylus
Синтаксис
Используйте вложенность с &, так будет видна зависимость и иерархическое дерево классов.
/* Плохо */
.project { /* ... */ }
.project__name { /* ... */ }
.project__description { /* ... */ }
/* Хорошо */
.project
// ...
&__name
// ...
&__description
// ...
Отступы
Используйте пробелы для отступов, не используйте табы и пробелы одновременно - стили не скомпилируются.
В этом примере ∙∙ - два пробела, а ―― - один отступ с табуляцией.
Используйте 2 пробела для отступов. В своем редакторе настройте табуляцию в виде пробелов, чтобы при нажатии на кнопку tab отступы делались в виде пробелов.
/* Плохо */
.project
――// ...
∙∙&__name
∙∙∙∙// ...
/* Хорошо */
.project
∙∙// ...
∙∙&__name
∙∙∙∙// ...
Отступы между классами
Между классами с группой свойств добавляте перенос строки для лучшей читабельности.
/* Плохо */
.project
// ...
&__name
// ...
&:before
// ...
/* Хорошо */
.project
// ...
&__name
// ...
&:before
// ...
Наименование составных блоков
Не используйте &- для описания имен составных блоков. Это затрудняет их поиск.
/* Плохо */
.project
// ...
&-container
// ...
&__name
// ...
&:before
// ...
/* Хорошо */
.project
// ...
&__name
// ...
&:before
// ...
.project-container
// ...
Один файл - один блок
Один файл — один компонент. Все стили для компонента должны быть описаны в этом файле. Стили других компонентов не должны встречаться в других файлах. Компонентами являются как блоки, так и элементы блоков и модификаторов (БЭМ терминология).
/* Плохо */
// main.styl
.project
// ...
&__name
// ...
&__before
// ...
.project-container
// ...
.portfolio
// ...
/* Хорошо */
// project.styl
.project
// ...
&:before
// ...
// project__name.styl
.project__name
// ...
// project-container.styl
.project-container
// ...
// portfolio.styl
.portfolio
// ...
Свойства в примесях
Примеси содержат в себе только блок свойств, селекторов внутри быть не должно.
/* Плохо */
.block
+below(666px)
&:first-child
margin-top: 5px
/* Хорошо */
.block
&:first-child
+below(666px)
margin-top: 5px
Итого
Исходя из всех предыдущих получаем следующую иерархию и последовательность
// Компонент
.component
// ...
// @media-примеси компонента
+below(640px)
// ...
// Псевдоэлементы компонента
&::after
// ...
// Псевдоклассы компонента
&:first-child
// ...
// Псевдоэлементы с псевдоклассом компонента
&::after
// ...
// Псевдоклассы компонента, влияющие на элементы
& .component__element
// ...
// Модификаторы компонента
.component_val
// ...
// Псевдоклассы модификатора компонента
&:first-child
// ...
// Псевдоэлементы модификатора компонента
&::after
// ...
// Модификаторы компонента, влияющие на элементы
& .component__element
// ...
// Элементы
.component__element
// ...
// @media-примеси элемента
+below(640px)
// ...
// Псевдоэлементы элемента
&::after
// ...
// Псевдоклассы элемента
&:first-child
// ...
// Псевдоэлементы с псевдоклассом элемента
&::after
// ...
// Модификаторы элемента
.component__element_val
// ...
// Псевдоклассы модификатора элемента
&:first-child
// ...
// Псевдоэлементы модификатора элемента
&::after
// ...
Переменные
При частой записи одинаковых значений следует использовать переменные:
- Название шрифтов
- Фирменные цвета
- Ресурсы в data-uri
Возможные проблемы и пути их решения
Когда комментируются свойства, нужно комментировать ещё и селектор, иначе он будет брать свойства вместе со следующим селектором или, если следующего селектора нет, компилятор выдаст ошибку.
/* Плохо */
.block
// ...
&__item
// color #08f
/* Хорошо */
.block
// ...
// &__item
// color #08f
Общие рекомендации
Используйте примеси (mixins) для частоповторяющихся участков кода и переменные для повторяющихся значений, но только в пределах одного компонента.
Используйте циклы для однотипных строк с различием в значениях, только если использование циклов целесообразно.
JavaScript
Зарезервированные слова
Не используйте зарезервированные слова в качестве ключей объектов. Они не будут работать в IE8.
/* Плохо */
var superman = {
default: { clark: 'kent' },
private: true
};
/* Хорошо */
var superman = {
defaults: { clark: 'kent' },
hidden: true
};
Ключевые слова
Не используйте ключевые слова (в том числе измененные). Вместо них используйте синонимы.
/* Плохо */
var superman = {
class: 'alien'
};
/* Плохо */
var superman = {
klass: 'alien'
};
/* Хорошо */
var superman = {
type: 'alien'
};
Копирование массива
Если вам необходимо скопировать массив, используйте Array::slice.
var len = items.length,
itemsCopy = [],
i;
/* Плохо */
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
/* Хорошо */
itemsCopy = items.slice();
Копирование похожий по свойствам на массив объект
Чтобы скопировать похожий по свойствам на массив объект (например, NodeList или Arguments), используйте Array::slice.
function trigger() {
var args = Array.prototype.slice.call(arguments);
...
}
Строки
Используйте одинарные кавычки '' для строк.
Строки длиннее 80 символов нужно разделять, выполняя перенос через конкатенацию строк.
/* Плохо */
var name = "Боб Дилан";
/* Хорошо */
var name = 'Боб Дилан';
/* Плохо */
var fullName = "Боб " + this.lastName;
/* Хорошо */
var fullName = 'Дилан ' + this.lastName;
/* Плохо */
var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. Не говори про обезъяну! Не слушай об обезьяне! Не думай об обезъяне!';
/* Плохо */
var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. \
Не говори про обезъяну! Не слушай об обезьяне! \
Не думай об обезъяне!';
/* Хорошо */
var errorMessage = (
'Эта сверхдлинная ошибка возникла из-за белой обезъяны. ' +
'Не говори про обезъяну! Не слушай об обезьяне! ' +
'Не думай об обезъяне!'
);
Функции
Никогда не объявляйте функцию внутри блока кода — например в if, while, else и так далее. Единственное исключение — блок функции. Вместо этого присваивайте функцию уже объявленной через var переменной. Условное объявление функций работает, но в различных браузерах работает по-разному.
Примечание. ECMA-262 устанавливает понятие блока как списка операторов. Объявление функции (не путайте с присвоением функции переменной) не является оператором.
Никогда не используйте аргумент функции arguments, он будет более приоритетным над объектом arguments, который доступен без объявления для каждой функции.
/* Объявление анонимной функции */
var anonymous = function () {
return true;
};
/* Объявление именованной функции */
var named = function named() {
return true;
};
/* Объявление функции, которая сразу же выполняется (замыкание) */
(function () {
console.log('Если вы читаете это, вы открыли консоль.');
})();
/* Плохо */
if (currentUser) {
function test() {
console.log('Плохой мальчик.');
}
}
/* Хорошо */
var test;
if (currentUser) {
test = function test() {
console.log('Молодец.');
};
}
/* Плохо */
function nope(name, options, arguments) {
// ...код...
}
/* Хорошо */
function yup(name, options, args) {
// ...код...
}
Свойства
Используйте точечную нотацию для доступа к свойствам и методам.
Используйте нотацию с [], когда вы получаете свойство, имя для которого хранится в переменной, а также если название свойства содержит дефис.
var luke = {
jedi: true,
age: 28
};
/* Плохо */
var isJedi = luke['jedi'];
/* Хорошо */
var isJedi = luke.jedi;
/* Если название свойства содержит дефис, то необходимо использовать нотацию с [] */
var isJedi = luke['jedi-master'];
var luke = {
jedi: true,
age: 28
};
function getProp(prop) {
return luke[prop];
}
var isJedi = getProp('jedi');
Переменные
Используйте одно var объявление переменных для всех переменных, и объявляйте каждую переменную на новой строке.
Объявляйте переменные, которым не присваивается значение, в конце. Это удобно, когда вам необходимо задать значение одной из этих переменных на базе уже присвоенных значений.
Присваивайте переменные в начале области видимости. Это помогает избегать проблем с объявлением переменных и областями видимости.
Все переменные которые явлюятся общими для всего тела функции выносите наверх, переменные относящиеся к отдельным функциональными частям или конструкциям (например переменные для циклов ) объявляйте рядом с этими функциональным частями или конструкциями.
/* Плохо */
var items = getItems();
var goSportsTeam = true;
var dragonball = 'z';
/* Хорошо */
var items = getItems(),
goSportsTeam = true,
dragonball = 'z';
/* Плохо */
var i, len, dragonball,
items = getItems(),
goSportsTeam = true;
/* Плохо */
var i, items = getItems(),
dragonball,
goSportsTeam = true,
len;
/* Хорошо */
var items = getItems(),
goSportsTeam = true,
dragonball,
length,
i;
/* Плохо */
function () {
test();
console.log('Делаю что-нибудь..');
//..или не делаю...
var name = getName();
if (name === 'test') {
return false;
}
return name;
}
/* Хорошо */
function() {
var name = getName();
test();
console.log('Делаю что-то полезное..');
//..продолжаю приносить пользу людям..
if (name === 'test') {
return false;
}
return name;
}
/* Плохо */
function() {
var name = getName();
if (!arguments.length) {
return false;
}
return true;
}
/* Хорошо */
function() {
if (!arguments.length) {
return false;
}
var name = getName();
return true;
}
Условные выражения и равенства
Используйте === и !== вместо == и !=.
Условные выражения вычисляются посредством приведения к логическому типу Boolean через метод ToBoolean и всегда следуют следующим правилам:
- Object всегда соответствует true
- Undefined всегда соответствует false
- Null всегда соответствует false
- Boolean остается неизменным
- Number соответствует false, если является +0, -0, или NaN, в противном случае соответствует true
- String означает false, если является пустой строкой '', в противном случае true. Условно говоря, для строки происходит сравнение не ее самой, а ее длины – в соответствии с типом number.
Используйте короткий синтаксис.
if ([0]) {
// true
// Массив(Array) является объектом, объекты преобразуются в true
}
/* Плохо */
if (name !== '') {
// ...код...
}
/* Хорошо */
if (name) {
// ...код...
}
/* Плохо */
if (collection.length > 0) {
// ...код...
}
/* Хорошо */
if (collection.length) {
// ...код...
}
Блоки кода
Используйте фигурные скобки для всех многострочных блоков.
/* Плохо */
if (test)
return false;
/* Хорошо */
if (test) return false;
/* Хорошо */
if (test) {
return false;
}
/* Плохо */
function() { return false; }
/* Хорошо */
function() {
return false;
}
Комментарии
Используйте /** ... */ для многострочных комментариев. Включите описание, опишите типы и значения для всех параметров и возвращаемых значений в формате jsdoc.
Используйте // для комментариев в одну строку. Размещайте комментарии на новой строке над темой комментария. Добавляйте пустую строку над комментарием.
Префикс TODO помогает другим разработчикам быстро понять, что вы указываете на проблему, к которой нужно вернуться в дальнейшем, или если вы предлагете решение проблемы, которое должно быть реализовано.
Эти комментарии отличаются от обычных комментариев, так как не описывают текущее поведение, а призывают к действию, например TODO -- нужно реализовать интерфейс. Такие комментарии также автоматически обнаруживаются многими IDE и редакторами кода, что позволяет быстро перемещаться между ними.
Используйте // TODO FIXME: для аннотирования проблем
Используйте // TODO: для указания решений проблем
/* Плохо */
// make() возвращает новый элемент
// основываясь на получаемом имени тэга
//
// @param tag
// @return element
function make(tag) {
// ...создаем element...
return element;
}
/* Хорошо */
/**
* make() возвращает новый элемент
* основываясь на получаемом имени тэга
*
* @param tag
* @return element
*/
function make(tag) {
// ...создаем element...
return element;
}
/* Плохо */
var active = true; // устанавливаем активным элементом
/* Хорошо */
// устанавливаем активным элементом
var active = true;
/* Плохо */
function getType() {
console.log('проверяем тип...');
// задаем тип по умолчанию 'no type'
var type = this._type || 'no type';
return type;
}
/* Хорошо */
function getType() {
console.log('проверяем тип...');
// задаем тип по умолчанию 'no type'
var type = this._type || 'no type';
return type;
}
function Calculator() {
// TODO FIXME: тут не нужно использовать глобальную переменную
total = 0;
return this;
}
function Calculator() {
// TODO: должна быть возможность изменять значение через параметр функции
this.total = 0;
return this;
}
Синтаксис
Данную картинку можно распечатать для удобства и повесить где - нибудь на виду, чтобы можно было быстро сверяться со стилем кода, к тому же запоминание будет идти гораздо быстрее.
Пробелы
Устанавливайте один пробел перед открывающей скобкой.
Используйте отступы, когда делаете цепочки вызовов.
/* Плохо */
function test(){
console.log('test');
}
/* Хорошо */
function test() {
console.log('test');
}
/* Плохо */
dog.set('attr',{
age: '1 year',
breed: 'Bernese Mountain Dog'
});
/* Хорошо */
dog.set('attr', {
age: '1 year',
breed: 'Bernese Mountain Dog'
});
/* Плохо */
$('#items').find('.selected').highlight().end().find('.open').updateCount();
/* Хорошо */
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
/* Плохо */
var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
/* Хорошо */
var leds = stage.selectAll('.led')
.data(data)
.enter().append('svg:svg')
.class('led', true)
.attr('width', (radius + margin) * 2)
.append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
Соглашение об именовании
Избегайте однобуквенных имен функций. Имена должны давать представление о том, что делает эта функция.
Используйте camelCase для именования объектов, функций и переменных.
Используйте PascalCase для именования конструкторов классов.
Используйте подчеркивание _ в качестве префикса для именования внутренних методов и переменных объекта.
Создавая ссылку на this, используйте название от самого класса в camelCase, вместо self/that/_this/me и т.п
Задавайте имена для функций. Это повышает читаемость сообщений об ошибках кода.
/* Плохо */
function q() {
// ...код...
}
/* Хорошо */
function query() {
// ...код...
}
/* Плохо */
var OBJEcttsssss = {};
var this_is_my_object = {};
function c() {};
var u = new user({
name: 'Bob Parr'
});
/* Хорошо */
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
name: 'Bob Parr'
});
/* Плохо */
function user(options) {
this.name = options.name;
}
var bad = new user({
name: 'Плохиш'
});
/* Хорошо */
function User(options) {
this.name = options.name;
}
var good = new User({
name: 'Кибальчиш'
});
/* Плохо */
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
/* Хорошо */
this._firstName = 'Panda';
function Rocket() {}
// ...
Rocket.prototype.startMessage = 'Houston, I\'m flying into space!';
/* Плохо */
Rocket.prototype.start = function () {
var _this = this;
_this.lightsCameraAction(function () {
console.log(_this.startMessage);
});
};
/* Хорошо */
Rocket.prototype.start = function () {
var rocket = this;
rocket.lightsCameraAction(function () {
console.log(rocket.startMessage);
});
};
/* Плохо */
var log = function(msg) {
console.log(msg);
};
/* Хорошо */
var log = function log(msg) {
console.log(msg);
};
Геттеры и сеттеры
Функции универсального доступа к свойствам не требуются.
Если вам необходимо создать функцию для доступа к переменной, используйте раздельные функции getVal() и setVal('hello')
Если свойство является логическим(boolean), используйте isVal() или hasVal()
Вы можете создавать функции get() и set(), но будьте логичны и последовательны – то есть не добавляйте свойства, которые не могут быть изменены через эти функции.
/* Плохо */
dragon.age();
/* Хорошо */
dragon.getAge();
/* Плохо */
dragon.age(25);
/* Хорошо */
dragon.setAge(25);
/* Плохо */
if (!dragon.age()) {
return false;
}
/* Хорошо */
if (!dragon.hasAge()) {
return false;
}
function Jedi(options) {
options || (options = {});
var lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
Jedi.prototype.set = function(key, val) {
this[key] = val;
};
Jedi.prototype.get = function(key) {
return this[key];
};
Конструкторы
Присваивайте метод прототипу вместо замены прототипа на другой объект. Замена прототипа на другой объект делает наследование невозможным.
Методы могут возвращать this для создания цепочек вызовов. Но стоит оставаться последовательным и обеспечить одинаковое поведение для всех методов, кроме геттеров.
Вы можете заменить стандартный метод toString(), но убедитесь, что он работает и не вызывает побочных эффектов.
function Jedi() {
console.log('new jedi');
}
/* Плохо */
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
/* Хорошо */
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
/* Плохо */
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
/* Хорошо */
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};
var luke = new Jedi();
luke.jump()
.setHeight(20);
Конструкторы
Присваивайте метод прототипу вместо замены прототипа на другой объект. Замена прототипа на другой объект делает наследование невозможным.
Методы могут возвращать this для создания цепочек вызовов. Но стоит оставаться последовательным и обеспечить одинаковое поведение для всех методов, кроме геттеров.
Вы можете заменить стандартный метод toString(), но убедитесь, что он работает и не вызывает побочных эффектов.
function Jedi() {
console.log('new jedi');
}
/* Плохо */
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
/* Хорошо */
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
/* Плохо */
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
/* Хорошо */
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};
var luke = new Jedi();
luke.jump()
.setHeight(20);
События
Подключая набор данных к событиям (как DOM-событиям, так и js-событиям, например, в Backbone), передавайте объект вместо простой переменной. Это позволяет в процессе всплытия событий добавлять к данному объекту дополнительную информацию.
/* Плохо */
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', function(e, listingId) {
//делаем что-нибудь с listing, например:
listing.name = listings[listingId]
});
/* Хорошо */
$(this).trigger('listingUpdated', { listingId : listing.id });
...
$(this).on('listingUpdated', function(e, data) {
// делаем что-нибудь с data.listingId
});
jQuery
Наименование переменных
Для jQuery-переменных используйте префикс $.
/* Плохо */
var sidebar = $('#sidebar');
/* Хорошо */
var $sidebar = $('#sidebar');
Кэширование запросов
Кэшируйте jQuery-запросы. Каждый новый jQuery-запрос делает повторный поиск по DOM-дереву, и приложение начинает работать медленнее..
/* Плохо */
function setSidebar() {
$('#sidebar').hide();
// ...код...
$('#sidebar').css({
backgroundColor: 'pink'
});
}
/* Хорошо */
function setSidebar() {
var $sidebar = $('#sidebar');
$sidebar.hide();
// ...код...
$sidebar.css({
backgroundColor: 'pink'
});
}
Поиск элементов
Для DOM-запросов используйте классический каскадный CSS-синтаксис $('.sidebar ul') или родитель потомок $('.sidebar > ul')
Используйте find для поиска внутри DOM-объекта.
Для поиска одного элемента используйте только идентификатор #id
Для поиска нескольких элементов однотипных по функционалу используйте класс с префиксом .js-* (для разделения названия класса использовать только дефис -), а не класс для стилизации элемента, название класса должно быть небольшим, но и понятным.
/* Плохо */
$('ul', '#sidebar').hide();
/* Плохо */
$('#sidebar').find('ul').hide();
/* Хорошо */
$('#sidebar ul').hide();
/* Хорошо */
$('#sidebar > ul').hide();
/* Хорошо */
$sidebar.find('ul').hide();
/* Плохо */
$('.menu button');
/* Плохо */
$('.menu button#menuToggler');
/* Плохо */
$('button#menuToggler');
/* Хорошо */
$('#menuToggler');
/* Плохо */
$('.navbar-menu__item');
/* Плохо */
$('.js-navbar-menu__item');
/* Хорошо */
$('.js-nav-link');
jQuery события
Для задания обработчика элементу используйте метод .on()
/* Плохо */
$input
.click(function () { /* ... */ })
.focus(function () { /* ... */ })
.blur(function () { /* ... */ });
/* Хорошо */
$input
.on('click', function () { /* ... */ })
.on('focus', function () { /* ... */ })
.on('blur', function () { /* ... */ });
/* Лучше */
// Несколько событий разделяются пробелами
$field.on('click focus', function () { /* ... */ });
$input.on({
// Несколько событий разделяются пробелами
'click focus': function () { /* ... */ },
blur: function () { /* ... */ }
});
Angular
Наименование файлов, папок и сущностей Angular
Папку, класс и html-тэг компонента называем по БЭМу.
Названия модулей пишем как fba.componentName
Название файлов через camelCase
Основной единицей компонента (точкой входа в компонент) является директива, ее название совпадает с названием компонента.
Внутри js файлов сущностей (контроллеров, сервисов, фильтров, моделей, фабрик) через camelCase название компонента + название сущности, за исключением Модели. (т.к. модель является сервисом, но в качестве названия сущности используем Model)

Cтруктура файлов
В новом создаваемом компоненте должны присутствовать jade, stylus, js, spec.js, html для разработки компонента изолированно от других и быстрого его просмотра.

Встроенные хэлперы Angular
По возможности используйте встроенные ангулярные хэлперы.
Для работы с массивами и объектами и манипуляциями элементами внутри них используйте библиотеку lodash
Общие рекомендации
- Для модификаторов используем одно слово
- Каждый элемент делать в виде отдельного модуля
- Данные для любых сущностей оформляются в виде модели
- По умолчанию привязываем директивы к элементам или к аттрибутам. Как исключение - к классам
- Наши css классы пишем в начале, а сторонние после
- Если классы без стилей, то пишем с префиксом js
Git
Наименование веток
Наименование веток производить по следующему принципу:
type/task-short-title/task-number, где
type - тип выполняемой задачи. Может быть
- feature - новая фича;
- fix - багофикс;
- docs - изменения в документации;
- style - форматирование кода или любые другие изменения, не влияющие на работу кода;
- refactor - изменения в коде, которые не относятся к фиксам или фиче;
- test - добавлен или обновлён тест;
- chore - измененения в сборщике, зависимостях и т.п.
task-number - номер выполняемой задачи в Accunote
task-short-title - краткое наименование задачи
/* Плохо */
shitty-shit
shitty/shit
shitty_shit
/* Хорошо */
fix/presets/666
feature/breakdowns/777
feature/breakdowns/775
style/sidebar/222
Написание коммитов
Описание коммита должно отражать суть выполненных изменений, не должно быть слишком коротким, но и не чересчур длинным. Желательно, чтобы другой разработчик, прочитав описание коммита, мог быстро понять чтобы было сделано.
/* Плохо */
1. Done
2. Some fixes
/* Хорошо */
1. Rewrite step module. Make customizable fbaForm module. Needs to fully integrate it to application.
2. Change targeting label, update campaign status in grid after change.