Спецификация DEPS
Введение
DEPS — технология для описания зависимостей в БЭМ.
DEPS-сущность — сущность, определяющая зависимость между БЭМ-сущностями.
Зависимости описываются в виде JavaScript-объекта в файлах с расширением .deps.js.
Полная запись DEPS-сущности имеет следующий вид:
/* DEPS-сущность */
({
block: 'block-name',
elem: 'elem-name',
mod: 'modName',
val: 'modValue',
tech: 'techName',
shouldDeps: [ /* БЭМ-сущность */ ],
mustDeps: [ /* БЭМ-сущность */ ],
noDeps: [ /* БЭМ-сущность */ ]
})
Примечание Все поля являются опциональными.
Используемые обозначения
Для короткой записи зависимостей в комментариях используются следующие условные обозначения:
/* b1 → b2 */— блокb1зависит от блокаb2(shouldDeps);/* b1 ⇒ b2 */— блокb1зависит от блокаb2(mustDeps);/* b1 → b1__e1 */— блокb1зависит от своего элементаb1__e1;/* b1 → b1_m1_v1 */— блокb1зависит от своего модификатораb1_m1_v1;/* b1 → b1__e1_m1_v1 */— блокb1зависит от модификатора своего элементаb1__e1_m1_v1;/* b1.js → b2.bemhtml */— блокb1в технологии реализации JavaScript зависит от блокаb2в технологии реализации BEMHTML.
Синтаксис DEPS
Представить DEPS-сущность в .deps.js-файле можно используя:
Круглые скобки
().
({
/* DEPS-сущность */
})
Литерал массива
[].
[{
/* DEPS-сущность */
},
{
/* DEPS-сущность */
}]
Поля DEPS-сущности
Можно разделить на следующие группы:
Определяющие БЭМ-сущность:
Определяющее технологию реализации БЭМ-сущности:
Определяющие зависимость:
Примечание Кроме описанных полей, вы можете использовать синтаксический сахар для повышения читаемости кода.
Поля определяющие БЭМ-сущность
Указывают для какой БЭМ-сущности необходимо подключить зависимость. Они являются опциональными и могут быть восстановлены из контекста по имени файла.
Поэтому записи для файла b1__e1_m1_v1.deps.js эквивалентны:
/* b1__e1_m1_v1 → b2 */
({
block: 'b1',
elem: 'e1',
mod: 'm1',
val: 'v1',
shouldDeps: { block: 'b2' }
})
/* b1__e1_m1_v1 → b2 */
({
shouldDeps: { block: 'b2' }
})
block
Поле block задает имя блока.
Тип: String.
// Блок b1
({
block: 'b1'
})
elem
Поле elem задает имя элемента.
Тип: String.
// Элемент b1__e1
({
block: 'b1',
elem: 'e1'
})
mod
Поле mod задает имя модификатора блока или элемента.
Тип: String.
// Модификатор блока b1_m1 со значением true
({
block: 'b1',
mod: 'm1'
})
// Модификатор элемента b1__e1_m1 со значением true
({
block: 'b1',
elem: 'e1',
mod: 'm1'
})
val
Поле val задает значение модификатора. Если val не указано, считается что значение модификатора равно true.
Тип: String, Boolean.
Ниже приведены примеры с указанием типа принимаемых данных:
Строка (
String).// Модификатор b1_m1_v1 со значением v1 ({ block: 'b1', mod: 'm1', val: 'v1' })Булев, Логический тип (
Boolean).// Модификатор b1_m1 со значением true ({ block: 'b1', mod: 'm1', val: true })
Поле определяющее технологию реализации БЭМ-сущности
Поле tech указывает, для какой технологии реализации необходимо подключить зависимость. В случае, когда tech не указано, зависимость считается общей и относится ко всем технологиям.
Подключение зависимостей по технологии используется, например, для того, чтобы собрать в клиентский JavaScript-бандл шаблоны только тех блоков, которые будут использованы в браузере. При такой схеме часть шаблонизации происходит на стороне сервера и, следовательно, некоторые шаблоны на клиенте никогда не используются.
Тип: String.
({
// Блок b1 в технологии JavaScript
block: 'b1',
tech: 'js'
})
Поля определяющие зависимость
Поля shouldDeps, mustDeps определяют зависимость, а noDeps отменяет
shouldDeps
Поле shouldDeps определяет зависимости, порядок подключения которых не важен.
Тип: Object[].
/* b1 → БЭМ-сущность */
({
block: 'b1',
shouldDeps: [
{ /* БЭМ-сущность */ }
]
})
mustDeps
Поле mustDeps определяет зависимости, которые попадут в результаты сборки до кода БЭМ-сущности, в которой эти зависимости объявляются.
Тип: Object[].
/* b1 ⇒ БЭМ-сущность */
({
block: 'b1',
mustDeps: [
{ /* БЭМ-сущность */ }
]
})
noDeps
Поле noDeps отменяет существующие зависимости, объявленные на других уровнях переопределения.
Тип: Object[].
/* common.blocks
b1 → БЭМ-сущность */
({
block: 'b1',
shouldDeps: [
{ /* БЭМ-сущность */ }
]
})
/* desktop.blocks */
({
block: 'b1',
noDeps: [
{ /* БЭМ-сущность */ }
]
})
В данном примере на уровне common.blocks по зависимостям подключается некая БЭМ-сущность, необходимая для реализации блока b1. На уровне desktop.blocks данная зависимость отменяется.
Синтаксический сахар
elem
Поле elem в качестве значения также может принимать массив строк (String[]):
// Элементы b1__e1 и b1__e2
({
block: 'b1',
elem: [
'e1',
'e2'
]
})
elems
Поле elems задает имя элемента и раскрывается в shouldDeps. Поэтому записи для файла b1.deps.js равнозначны:
({
/* b1 → b1__e1; b1 → b1__e2 */
block: 'b1',
elems: [
'e1',
'e2'
]
})
({
/* b1 → b1__e1; b1 → b1__e2 */
block: 'b1',
shouldDeps: [
{
elem: [
'e1',
'e2'
]
}
]
})
Тип: String, Object, String[], Object[].
Ниже приведены примеры с указанием типа принимаемых данных:
String./* b1 → b1__e1 */ ({ block: 'b1', elems: 'e1' })Объект (
Object)./* b1 → { ElemDepsEntity } */ ({ block: 'b1', elems: { /* { ElemDepsEntity } */ } })Массив строк (
String[])./* b1 → b1__e1; b1 → b1__e2 */ ({ block: 'b1', elems: [ 'e1', 'e2' ] })Массив объектов (
Object[])./* b1 → { ElemDepsEntity }; b1 → { ElemDepsEntity } */ ({ block: 'b1', elems: [ { /* { ElemDepsEntity } */ }, { /* { ElemDepsEntity } */ } ] })
ElemDepsEntity — это JavaScript-объект со следующими полями:
/* elemDepsEntity */
({
elem: 'elem-name',
mod: 'modName',
val: 'modValue',
tech: 'techName',
shouldDeps: [ /* БЭМ-сущность */ ],
mustDeps: [ /* БЭМ-сущность */ ],
noDeps: [ /* БЭМ-сущность */ ]
})
Примечание Поле
elemявляется обязательным.
mods
Поле mods задает имя и значение модификатора и раскрывается в shouldDeps. Поэтому записи для файла b1.deps.js равнозначны:
({
/* b1 → b1_m1_v1; b1 → b1_m1_v2 */
block: 'b1',
mods: { m1: [
'v1',
'v2'
]
}
})
({
/* b1 → b1_m1_v1; b1 → b1_m1_v2 */
block: 'b1',
shouldDeps: [
{
block: 'b1',
mod: 'm1',
val: 'v1'
},
{
block: 'b1',
mod: 'm1',
val: 'v2'
}
]
})
Тип: String[], Object.
Ниже приведены примеры с указанием типа принимаемых данных:
Массив строк (
String[])./* b1 → b1_m1; b1 → b1_m2 */ ({ block: 'b1', mods: [ 'm1', 'm2' ] })Объект, где значением свойства может быть:
Строка (
String)./* b1 → b1_m1_v1 */ ({ block: 'b1', mods: { m1: 'v1' } })Булев, Логический тип (
Boolean)./* b1 → b1_m1 */ ({ block: 'b1', mods: { m1: true } })Массив строк (
String[])./* b1 → b1_m1_v1; b1 → b1_m1_v2 */ ({ block: 'b1', mods: { m1: [ 'v1', 'v2' ] } })
shouldDeps, mustDeps, noDeps
Тип: String, Object, String[].
Ниже приведены примеры с указанием типа принимаемых данных:
Строка (
String)./* b1 → b2 */ ({ block: 'b1', shouldDeps: 'b2' })Объект (
Object)./* b1 → БЭМ-сущность */ ({ block: 'b1', shouldDeps: { /* БЭМ-сущность */ } })Массив строк (
String[])./* b1 → b2; b1 → b3 */ ({ block: 'b1', shouldDeps: [ 'b2', 'b3' ] })
Примеры деклараций
Подключение блока
b1 → b2 — блок b1 зависит от блока b2.
Зависимость может быть объявлена в виде:
Массива объекта (
Object[])./* b1 → b2 */ ({ block: 'b1', shouldDeps: [ { block: 'b2' } ] })Синтаксический сахар
Строки (
String)./* b1 → b2 */ ({ block: 'b1', shouldDeps: 'b2' })Объекта (
Object)./* b1 → b2 */ ({ block: 'b1', shouldDeps: { block: 'b2' } })Массива строк (
String[])./* b1 → b2 */ ({ block: 'b1', shouldDeps: [ 'b2' ] })
Подключение элемента
b1 → b1__e1 — блок b1 зависит от своего элемента b1__e1.
Зависимость может быть объявлена в виде:
Массива объектов (
Object[])./* b1 → b1__e1 */ ({ block: 'b1', shouldDeps: [ { block: 'b1', elem: 'e1' } ] })Синтаксический сахар
Строки (
String)./* b1 → b1__e1 */ ({ block: 'b1', elems: 'e1' })Объекта (
Object)./* b1 → b1__e1 */ ({ block: 'b1', shouldDeps: { elem: 'e1' } })/* b1 → b1__e1 */ ({ block: 'b1', elems: { elem: 'e1' } })Массива строк (
String[])./* b1 → b1__e1 */ ({ block: 'b1', elems: [ 'e1' ] })Массива объектов (
Object[])./* b1 → b1__e1 */ ({ block: 'b1', elems: [ { elem: 'e1' } ] })
Подключение булевого модификатора
b1 → b1_m1 — блок b1 зависит от своего булевого модификатора b1_m1.
Зависимость может быть объявлена в виде:
Массива объектов (
Object[])./* b1 → b1_m1 */ ({ block: 'b1', shouldDeps: [ { block: 'b1', mod: 'm1', val: true } ] })Синтаксический сахар
Объекта (
Object)./* b1 → b1_m1 */ ({ block: 'b1', shouldDeps: { block: 'b1', mod: 'm1', val: true } })/* b1 → b1_m1 */ ({ block: 'b1', shouldDeps: { mod: 'm1', val: true } })/* b1 → b1_m1 */ ({ block: 'b1', mods: { m1: true } })Массива строк (
String[])./* b1 → b1_m1 */ ({ block: 'b1', mods: [ 'm1' ] })
Подключение модификатора вида «ключ-значение»
b1 → b1_m1_v1 — блок b1 зависит от своего модификатора вида «ключ-значение» b1_m1_v1.
Зависимость может быть объявлена в виде:
Массива объектов (
Object[])./* b1 → b1_m1_v1 */ ({ block: 'b1', shouldDeps: [ { block: 'b1', mod: 'm1', val: 'v1' } ] })Синтаксический сахар
Объекта (
Object)./* b1 → b1_m1_v1 */ ({ block: 'b1', shouldDeps: { mod: 'm1', val: 'v1' } })/* b1 → b1_m1_v1 */ ({ block: 'b1', mods: { m1: 'v1' } })/* b1 → b1_m1_v1 */ ({ block: 'b1', mods: { m1: [ 'v1' ] } })
Подключение зависимостей по технологии
b1.js → b2.bemhtml — блок b1 в технологии реализации JavaScript зависит от блока b2 в технологии реализации BEMHTML.
Зависимость может быть объявлена в виде:
Массива объектов (
Object[])./* b1.js → b2.bemhtml */ ({ block: 'b1', tech: 'js', shouldDeps: [ { block: 'b2', tech: 'bemhtml' } ] })Синтаксический сахар
Объекта (
Object)./* b1.js → b2.bemhtml */ ({ block: 'b1', tech: 'js', shouldDeps: { block: 'b2', tech: 'bemhtml' } })
elem & elems
Совместное использование полей elem и elems.
/* b1__e1 → b1__e2 */
({
block: 'b1',
elem: 'e1',
elems: [
'e1',
'e2'
]
})
Примечание Зависимости сами на себя
/* b1__e1 → b1__e1 */не имеют смысла и поэтому игнорируются.
mod & mods
Совместное использование полей mod и mods.
/* b1_m1_v1 → b1_m1_v2 */
({
block: 'b1',
mod: 'm1',
val: 'v1',
mods: { m1: [
'v1',
'v2'
]
}
})
Примечание Зависимости сами на себя
/* b1_m1_v1 → b1_m1_v1 */не имеют смысла и поэтому игнорируются.
elems & mods
Совместное использование полей elems и mods.
/* b1 → b1__e1; b1 → b1_m1_v1 */
({
block: 'b1',
elems: 'e1',
mods: { m1: 'v1' }
})