Во времена React.js и подобных вещей хочется и в bem.js чего то подобного.
Из дискуссии https://ru.bem.info/forum/385/ ничего внятного не вышло.
Предлагаю вариант своей идеи как это можно сделать.
Основная идея
По аналогии с React оперировать виртуальным деревом, но не в терминах DOM а в терминах БЭМ.
При загрузке страницы вместе с базовым HTML телом страницы отдается bemjson и скомпилированный bemtree или bemhtml.
Создается виртуальное БЭМ дерево, далее из него формируется html и рендерится на страницу.
Пример
На текущий момент bem.js оперирует DOM нодами посредством jQuery.
Нужна реализация оперирующая БЭМ деревом (по факту развернутый bemjson) и обновляющая данные на странице при его изменении.
Скажем браузеру отдается страница вида
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body class="page" bem-json="....">
// тут может быть отрендереный на сервере bemjson
</body>
</html>
Сам bemjson имеет вид
{
block: 'comment-box',
js: {
url: 'comments.json',
pollInterval: 2000
},
content: [
{
block: 'comment-list',
content: [
{
author: 'Pete Hunt',
content: 'This is one comment'
},
{
author: 'Jordan Walke',
content: 'This is *another* comment'
}
]
}
]
}
Ну и сами блоки
JSONBEMDOM.decl('comment-box', {
onSetMod: {
js: {
inited: function() {
// метод findBlockInside спускается по нашему виртуальному БЭМ дереву
// и пытается найти bemjson блок comment-form
this.form = this.findBlockInside('comment-form');
this.commentsList = this.findBlockInside('comment-list');
this.form.on('submit', this._submitHandler);
this._loadCommentsFromServer();
setInterval(this._loadCommentsFromServer, this.params.pollInterval);
}
}
},
getDefaultParams: function() {
return {
data: [],
url: '',
pollInterval: null
}
},
_loadCommentsFromServer: function() {
$.getJson(this.params.url).done(function(comments) {
/**
* метод content() ожидает аргумент в синтаксисе bemjson
* который он применяет к `content` параметру блока в виртуальном БЭМ дереве
*/
this.commentsList.content(comments);
}.bind(this));
},
_submitHandler: function(e) {
e.preventDefault();
/**
* метод content() без аргументов отдает из дерева
* параметр `content` элемента, если это инпут то его значение
*/
var text = this.elem('text').content();
var author = this.elem('author').content();
$.post(this.params.url, {
text: text,
author: author
}).done(function (comment) {
var comments = this.commentsList.content();
comments = comments.concat([comment]);
this.commentsList.content(comments);
}.bind(this));
}
});
bem.js сам отслеживает изменения в виртуальном БЭМ дереве, делает слепок отличий, накладывает на него bemhtml/bemtree и инъектит его в текущий html.
В итоге мы имеем на клиенте
- Всю мощь декларативной шаблонизации
bemhtml/bemtree
- Красивый и структурированный
bemjson на клиенте
- Производительность из-за виртуального БЭМ дерева.