bem-site / bem-forum-content-ru

Content BEM forum for Russian speak users
MIT License
56 stars 6 forks source link

BEMTREE и BEMHTML на клиенте #387

Open Guria opened 9 years ago

Guria commented 9 years ago
modules.define(
    'i-bem__dom',
    ['BEMTREE', 'BEMHTML', 'vow'],
    function(provide, BEMTREE, BEMHTML, Vow, BEMDOM) {
        provide(BEMDOM.decl(this.name, {}, {
            applyBemjson : function(bemjson, ctx, useBemtree) {
                var promise;
                if (useBemtree) {
                    promise = BEMTREE.apply(bemjson)
                } else {
                    var deferred = Vow.defer();
                    deferred.resolve(bemjson);
                    promise = deferred.promise();
                }

                return promise
                    .then(function(bemjson){
                        BEMDOM.update(ctx, BEMHTML.apply(bemjson));
                    })
            }
        }))
    });

Ок или что-то не так?

apsavin commented 9 years ago

Лучше, имхо, разбить на два метода. Один синхронный - только bemhtml. Другой асинхронный - он использует первый внутри себя, когда отработает bemtree.

Guria commented 9 years ago

@apsavin Да, спасибо. Думал над этим. Но мне показалось, что лучше не разводить разные способы вызова. Я это в ангуляре планирую вызывать, поэтому не хотелось прокидывать эту неконсистентность (синхронный и асинхронный методы) дальше.

Guria commented 9 years ago

названия методам не поможешь выбрать? :)

Guria commented 9 years ago

Тут есть ещё проблемка. Инициализации блоков не проходит, если их нету у кого-нибудь в ymodules зависимостях. Никак не пойму кто же реквайрит все блоки при обычной автоматической инициализации.

apsavin commented 9 years ago

Названия выбрать - это уже слишком сложно)

При обычной автоматической инициализации все блоки-наследники i-bemdom [авто-рекварятся](https://github.com/bem/bem-core/blob/2ce9b3425801856056ca04ceed2c8bfdf7e5f7b2/common.blocks/i-bem/dom/i-bem__dom.js#L1518).

Guria commented 9 years ago

О, спасибо.

tadatuta commented 9 years ago

можно сохранить финальный метод всегда асинхронным, но разбить логику на getBemjson(data), getHtml(bemjson) и render(bemjson, ctx, useBemtree) для дополнительного слоя абстракции над конкретным шаблонизатором и способом работы с ним — позже можно будет легко переопределить только нужную часть.

isuvorov commented 9 years ago

@guria Алексей, а есть какой-нибудь пример как это можно использовать? тоже задача рендерить блоки на лету

Guria commented 9 years ago

Ну в данном случае вызов BEMDOM.render(bemjson, ctx, true) отрендерит исходный bemjon с помощью bemtree+bemhtml, вставит в дом ноду ctx и вызовет волну инициализации блоков.

Guria commented 9 years ago

@tadatuta Переписал так:

modules.define(
    'i-bem__render',
    ['BEMTREE', 'BEMHTML', 'jquery', 'vow', 'i-bem__dom', 'i-bem__dom_init'],
    function(provide, BEMTREE, BEMHTML, $, Vow, BEMDOM, _) {
        provide(BEMDOM.decl(this.name, {}, {
            renderHtml : function(bemjson){
                return BEMDOM.append($(document.createElement('div')), BEMHTML.apply(bemjson));
            },

            processBemjson : function(data){
                return BEMTREE.apply(data);
            },

            render : function(bemjson, useBemtree) {
                var promise;

                if (useBemtree) {
                    promise = BEMDOM.processBemjson(bemjson);
                } else {
                    var deferred = Vow.defer();
                    deferred.resolve(bemjson);
                    promise = deferred.promise();
                }

                return promise
                    .then(function(bemjson){
                        return BEMDOM.renderHtml(bemjson);
                    });
            }
        }))
    });

Почему BEMDOM внутри функции render не имеет методов processBemjson и renderHtml? Как их правильно вызвать в этом случае?

Guria commented 9 years ago

Остановился на таком варианте:

modules.define(
    'i-bem__render',
    ['BEMTREE', 'BEMHTML', 'jquery', 'vow', 'i-bem__dom', 'i-bem__dom_init'],
    function(provide, BEMTREE, BEMHTML, $, Vow, BEMDOM, _) {
        function renderHtml(bemjson){
            return BEMDOM.append($(document.createElement('div')), BEMHTML.apply(bemjson));
        }

        function processBemjson(data){
            return BEMTREE.apply(data);
        }

        provide(BEMDOM.decl(this.name, {}, {
            renderHtml : renderHtml,

            processBemjson : processBemjson,

            render : function(bemjson, useBemtree) {
                var promise;

                if (useBemtree) {
                    promise = processBemjson(bemjson);
                } else {
                    var deferred = Vow.defer();
                    deferred.resolve(bemjson);
                    promise = deferred.promise();
                }

                return promise
                    .then(function(bemjson){
                        return renderHtml(bemjson);
                    });
            }
        }))
    });