-
-
Save a-x-/39242cb6ee00231900f0 to your computer and use it in GitHub Desktop.
| // TOC | |
| // Intro | |
| // # New BEM based blocks concept — BEMS | |
| // # New 3-step templating concept | |
| // Example | |
| /** | |
| # New BEM based blocks concept — BEMS | |
| ## Нейминг: Не мода, а поле | |
| Вместо термина "мода" (mode), используется "поле" (prop) | |
| Ибо, какая нафиг мода (=режим), если это просто поле? | |
| ## mods | |
| Модификаторы расщепляются на mods (view) и state | |
| ## mix | |
| Миксы расщепляются на mix и base (наследование) | |
| */ | |
| /** | |
| # New 3-step templating concept (data-data-bemjson-html) | |
| bempriv is optional. Uses for complex blocks | |
| [BEMPRIV] XJT BEMHTML | |
| -- data ---------@-- data ------@-- bemjson --@-- html | |
| fp js code --/ xjt tpls --/ bemhtml --/ | |
| instead of old model: | |
| [BEMPRIV] BEMTREE BEMHTML | |
| -- data ---------@-- bemjson --@--- bemjson --@-- html | |
| js code --/ bemtree --/ bemhtml --/ | |
| Clear Data aren't contain `{ block: 'foo' }` | |
| xjt - Data JSON to BEMJSON transition tool (concept) | |
| ## Нейминг: не ctx, а data | |
| ## Доопределения и переопределения | |
| Merge strategies | |
| merge: 'override', // by entire propSet - переопределение | |
| merge: 'extend', // by entire props (default) - доопределение, переопределяющее имеющиеся поля | |
| merge: 'deep', // deep props scan, not workin' on arrays - глубокое доопределение | |
| Note: Массивы не мержатся (На массивах всегда выставляется стратегия extend) | |
| */ | |
| // Example | |
| // common: | |
| [{ | |
| // match section (block, elem, mods, elemMods) | |
| block: 'carousel', | |
| // apply (body) section (state, content, mix) | |
| state: { offset: 'start' }, // start|middle|end | |
| // gives -> [{elem:'item'..},{elem:'item'..},{elem:'item'..},,,] | |
| // .items <- this.data.items = [{thumb:{},title,,},,,] | |
| content: { mapData: '.items', elem: 'item' }, | |
| }, | |
| { | |
| block: 'carousel', elem: 'item', | |
| state: { theme: 'square' }, | |
| url: '.thumb.url', | |
| title: '.title' // original data: this.data.items[i].title | |
| }] | |
| // deskpad: | |
| [{ | |
| merge: 'override', // not recomended at all | |
| block: 'carousel', elem: 'item', | |
| state: { hovered: false }, // after override: { hovered: false } (loose theme: 'square' ) | |
| }] | |
| // desktop: | |
| [{ | |
| merge: 'deep', | |
| // matches `carousel__has-header` only | |
| block: 'carousel', mods: { 'has-header': true }, | |
| content: [ { elem: 'header' }, '::content' ] // access super block prop | |
| }, | |
| { | |
| merge: 'deep', | |
| block: 'carousel', elem: 'item', | |
| state: { theme: 'rect' }, // after merge: { full: true, theme: 'rect' } | |
| content: '.title' | |
| }] |
В реальном проекте код bemhtml часто становится излишне сложным и нечитаемым с обилием имеративщины
Но куда больше у нас есть плохих привов, с обилием present'тативщины
Сложно не нарушать баланс данные/представление (то и дело всё скатывается в PHP)
И без имеративных конструкций не обходится
Возникает и такая проблема: Если полностью вынести представление из (bem)priv,
то в bemhtml (или в bemtree) придётся написать map'ы, а это при всей декларативнсти FP всё-равно too much императивно для декларативного шаблона
Детали:
Некоторые проблемы bempriv-bemtree-bemhtml
- в привах и маппинг данных и накладывание view
- в bemhtml/bemtree обилие иперативщины
- ...map(...,function(){...})
- applyNext(function(){this.mods || ...})
- this.ctx.foo.push(...))
Проблема: Доопределения и переопределения
{ someProp: '::someProp' } // access super prop as is
{ someProp: ['::someProp', 'foo', 'bar'] } // access super prop to embeding
{ someProp: function(baseProp, ctx){} } // complex access super prop - not recomended
Merge strategies
merge: 'override', // by entire propSet
merge: 'extend', // by entire props
merge: 'deep', // deep props scan, not workin' on arrays
merge: 'inherit', // inherit parent propSet strategy or default
merge: 'default', // = 'extend'
На массивах всегда выставляется стратегия extend
NOTE: Не следует на js писать доопределение встраивание внутрь массива,
Вместо этого поместить в массив заглушки,
которые уже переопределять.
Фича: Сквозные поля для блоков
this.blockData (= this.data блока, к которому относятся элементы)
Сахар: Блоки-Алиасы
bemhtml
block('share-dropdown').replace()({ block: 'dropdown', popup: 'share' })xjt
{ block: 'share-dropdown', is: { block: 'dropdown', popop: 'share' } }Синтаксис: Маппинг данных на блоки и элементы
{ mapData: '.key1.nestedKey2', elem: 'el' }
Результат:
// [{elem:'el',,},{elem:'el',,},{elem:'el'},,,]
Концептуальная проблема: теряется гибкость?
Q: раньше можно было где угодно в данных (в BEMPRIV/vanilla.node.js) выставить поле представления (block/elem)
и включить шаблонизацию
A: Да и теперь можно в XJT, и более декларативно.
BEMPRIV тоже можно использовать между бекендом и XJT для слодных блоков, но не обязательно
mix или наследование?
И о и другое
mix
блок foo-bar в content'е блока qux-pux, миксуется на элемент foo этого родительского блока
{ mix: [{ block: 'qux-pux', elem: 'foo' }] } // or mix: ['qux-pux__foo']base
блок foo-bar наследует блок bar
{ block: 'foo-bar', base: { block: 'bar'} } // or base: 'bar'Q: Как отлаживать? Мы только отказались от bemhtml DSL
A: в любом месте XJT-шаблона предполагается возможным заменить короткую запись на функцию и поставить туда console.log или debugger, а затем вернуть обратно декларативную запись.
Кроме того, есть идея использовать спец-символ в строках типа '.key' для включения отладки
например: '!log!.key' будет выводить подробный лог проходящих через маппинг данных со всеми "явками и паролями"
Небольшое сравнение читаемости синтаксисов BEM-XJST и XJT