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

Во времена 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 на клиенте
  • Производительность из-за виртуального БЭМ дерева.