Войти с помощью github
Форум /

Настоящим постом хочу продемонстрировать вам как будет выглядет API bem-xjst v8.x. Все пока на стадии RC, поэтому хочу выслушать ваше мнение по поводу всего этого.

Изменения, которые войдут в v8.x

  • Все режимы теперь ведут себя одинаково: переопределяют значение из BEMJSON. (major)
  • Добавлены недостающие режимы: mods() и elemMods() для установки модификаторов. (minor)
  • Добавлены шорткаты режимов для добавления: addMix(), addAttrs(), addMods(), addElemMods(), addJs(). (minor)
  • Добавлены шорткаты для добавления content: appendContent() и prependContent(). (minor)

TLDR; Песочница bem-xjst v8.x RC: https://goo.gl/ZeY4xL, в которой можно попробовать все эти вкусности…

Технические подробности

1. Все режимы теперь ведут себя одинаково: переопределяют значение из BEMJSON. (major)

Сейчас значение из шаблона режима content(), bem(), cls(), tag() переопределяет значение указанное в BEMJSON. Если вам нужно расширить значение из BEMJSON в шаблоне нужно использовать applyNext() и this.extend()/concat().

Однако режимы mix(), js(), attrs() сейчас расширяют значение из BEMJSON.

Разное поведение режимов вносит некоторый раздрай и постоянно приходится держать в уме кто как себя ведет.

В v8.x мы привели все режимы к одинаковому явному поведению: переопределение значения из BEMJSON. Если вам нужно добавить что-либо, то теперь это можно будет сделать в явном виде — см п.3.

2. Добавлены недостающие режимы: mods() и elemMods() для установки модификаторов. (minor)

Под капотом эти режимы просто шорткаты к уже привычным всем конструкциям:

// mods()({something: myValue})
def()(function() {
    this.mods = {something: myValue};
    return applyNext();
});

и

// elemMods()({something: myValue})
def()(function() {
    this.elemMods = {something: myValue};
    return applyNext();
});

Как видно из примеров режимы mods() и elemMods() не имеют своей собственно очереди шаблонов, а добавляют шаблоны в стек к режиму def().

По умолчанию mods() и elemMods() возвратят вам значения из this.mods и this.elemMods соответственно.

Пример:

// BEMJSON
{ block: 'b' }

//Шаблоны
block('b').def()(function() {
  return JSON.stringify(apply('mods'));
});

//Результатом будет:
[]

3. Добавлены шорткаты режимов для добавления: addMix(), addAttrs(), addMods(), addElemMods(), addJs().

Так как все режимы теперь переопределяют значение, то чтобы компенсировать необходимость писать applyNext() для накапливания результата были введены шорткаты для уже существующих режимов add*().

Под капотом addJs()({ somekey: someval }) это

js()(function() {
  return this.extend(applyNext(), { somekey: someval });
});

Под капотом addMix()({block: 'mixed' }) это

mix()(function() {
  var res = applyNext();
  if (!Array.isArray(res)) res = [ res ];

  return res.push({block: 'mixed' })
})

Для остальных режимов аналогично. Как видно из примера шорткаты add*() не имеют своего стека шаблонов, а просто добавляют шаблон в стек соответствующего режима.

И, естественно, вы можете накапливать результат:

// Шаблоны
block('b')(
   addJs()({ a: 1 })
   addJs()({ b: 2 })
   addJs()({ c: 3 })
);

// BEMJSON
{ block: 'b' }

// Результат:
<div class="b b_type_awesome i-bem" data-bem='{"b":{"a":1,"b":2,"c":3}}'></div>

4. Добавлены шорткаты для добавления content: appendContent() и prependContent().

// Шаблоны:
block('b')(
    appendContent()(', templates!'),
    appendContent()('!!1'),
    prependContent()('(〜 ̄▽ ̄)〜 ')
);

// BEMJSON
{ block: 'b', content: 'Hello' }

// Результат:
<div class="b">(〜 ̄▽ ̄)〜 Hello, templates!!!1</div>

Как вы уже наверное догадались, это тоже шорткаты и они добавляют шаблоны в стек режима content(). Пример:

// appendContent()(', templates!') это тоже самое что и:
content()(function() {
  return [
    applyNext(),
    ', templates!'
  ];
});