bem-site / bem-forum-content-ru

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

BEMTREE+BEMHTML+bemjson #157

Open const-l opened 9 years ago

const-l commented 9 years ago

Приветствую! Вопрос, возможно, глупый, но все же хотелось бы узнать мнение людей, которые не такие "зеленые" в этом деле как я. Маленькая предистория: вдохновившись записями мастер-класса BEMup'a в Москве я принялся за дело - сайт получает данные из БД, они обрабатываются в BEMTREE, полученный bemjson в BEMHTML, а оттуда на клиент. Роутингом всего этого занимается express. Все отлично и прекрасно, но есть одно "но". Дело в том, что на всех страницах (точнее сказать по всем адресам, которые знает мое приложение) есть одинаковый контент в виде менюшки, лого и т. д. Так вот хотелось бы всю вот эту, так сказать, "статику" один раз описать в файле *.bemjson и забыть. Очень уж лениво каждый раз после обработки БЕМ-деревом оборачивать полученный bemjson своими блоками, да и если это ajax-запрос, то при таком подходе результат выходит мягко говоря забавный. Думаю, многие сталкивались с подобным, потому буду рад Вашему совету

qfox commented 9 years ago

Еще не пробовали в page.bemtree или root.bemtree эту менюшку описывать? В этом случае она всегда будет только там и нигде еще.

tadatuta commented 9 years ago

@const-l Привет! Не уверен, что правильно понял вопрос, опишу в двух словах схему, по которой это все задумано, если окажется, что ответил не на то — буду раз уточняющим вопросам.

На стороне express окажется функция render вроде такой (сниппет из реального проекта, добавил комментов):

BEMTREE.apply({
        // корневой блок, в его шаблоне будем пробрасывать нужные данные вглубь по дереву
        block: 'root', 
        // BEMJSON-контекст, который требуется построить
        context: context,
        // расширяем данные, которые нужны всем роутам
        data: Objects.extend({
            user: req.user // например, сессия пользователя
        }, data) // данные, передаваемые в шаблоны
    }).then(function(bemjson) {
        // в dev-режиме и в случае, если в url передано `?bemjson=1`, будем отдавать BEMJSON для более удобной отладки
        if (isDev && query.bemjson) return res.send('<pre>' + JSON.stringify(bemjson, null, 4) + '</pre>');

        try {
            var html = tmpl.BEMHTML.apply(bemjson);
        } catch(e) {
            console.log('BEMHTML ERROR', e);
            return res.sendStatus(500);
        }

        // положим сгенерированный шаблон в кэш, если необходимо
        useCache && (cache[cacheKey] = {
            timestamp: new Date(),
            html: html
        });

        res.send(html);
    });

Теперь, чтобы мочь рендерить только нужные блоки вместо целой страницы для AJAX-запросов, в шаблоне root.bemtree можно написать что-то типа:

block('root').def()(function() {
    var ctx = this.ctx;

    this.data = ctx.data; // пробрасываем поле data, чтобы оно было доступно во всех блоках

    if (ctx.context) return applyCtx(ctx.context); // если был передан какой-либо `context`, то генерируем дерево, начиная с него

    // если context не был передан, то генерируем страницу целиком
    return applyCtx({
        block: 'page',
        title: ctx.data.title,
        favicon: '/favicon.ico',
        styles: [
            {
                elem: 'css',
                url: '/_index.css'
            }
        ],
        scripts: [
            {
                elem: 'js',
                url: '/_index.js'
            }
        ],
        head: [
            { elem : 'meta', attrs : { name : 'viewport', content : 'width=device-width, initial-scale=1' } },
        ],
        mods: {
            theme: 'islands',
            view: ctx.data.view
        }
    });
});

Пользоваться этим можно так:

app.get('/', function(req, res) {
    // если прилетел ajax-запрос, генерируем BEMJSON начиная с блока `content`, иначе — весь проект целиком
    // первый аргумент функции — data, второй — context
    req.xhr ? render({}, { block: 'content' }) : render({ title: 'Крутой проект' });
});
const-l commented 9 years ago

@zxqfox, Вариант)) Я, видимо, зациклился на bemjson'e, так как он мне кажется более наглядным, что ли))

@tadatuta, да, вопрос именно в этом. Благодарю за наглядность

voischev commented 9 years ago

@tadatuta Еее! :+1: :)

Guria commented 9 years ago

А есть публичные демо проекты организованные аналогично? Чтобы подробнее покурить как это работает.

tadatuta commented 9 years ago

@Guria прямо сейчас нормально оформленных нет :(

у меня есть большое желание обобщить текущий опыт в виде реиспользуемого модуля/модулей и подробно описать подход к разработке с примерами, но когда до этого дойдут руки — не знаю.

aimuzov commented 9 years ago

у меня есть большое желание обобщить текущий опыт в виде реиспользуемого модуля/модулей и подробно описать подход к разработке с примерами, но когда до этого дойдут руки — не знаю.

@tadatuta Еще работаете над этим? :)

tadatuta commented 9 years ago

@Immuzov Традиционно зашли с дальнего края и переписали саму работу BEMHTML, сейчас переводим на новые рельсы и BEMTREE. Так что по теме вопроса мне все еще предложить нечего. Но зато ребята из сообщества выложили свои наработки: https://github.com/apsavin/bnsf https://github.com/voischev/express-bemtree-project-stub

aimuzov commented 9 years ago

@tadatuta Спасибо!