bem-site / bem-forum-content-ru

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

Помогите составить условие в bemtree #194

Open 4ok opened 9 years ago

4ok commented 9 years ago

Как правильно составить условие в bemtree для блока, чтобы он не выводился при определенных условиях

Например у меня есть блок block-a и я хочу чтобы он вообще не появился в результирующем bemtree, если в нем this.ctx.data не определено. У меня получился следующий рабочий вариант:

block('block-a')
(
    match(this.ctx.data)
    (
        content()
        (
            function ()
            {
                var ctx = this.ctx;
                var result;

                // Some code ....

                return result;
            }
        )
    ),

    match(this.ctx.block && !this.ctx.data && !this.ctx.content) // @todo !!!
    (
        function ()
        {
            this.block = undefined;
            this.ctx = {};

            return applyNext();
        }
    )
);

Но мне кажется, что условие может быть более простым, но у меня не выходит.

Буду рад любой подсказке, заранее спасибо!

tadatuta commented 9 years ago

@4ok Для исходного условия достаточно просто

block('block-a').match(function() { return !this.ctx.data; }).def()('');

Но старик Оккам рекомендует, если это возможно по коду, не создавать блок на уровне родителя:

block('parent').content()(function() {
    var data = this.ctx.data;
    return [
        data ? {
            block: 'block-a',
            data: data
        } : '',
        {
            block: 'block-b'
        }
    ];
});
voischev commented 9 years ago

@tadatuta +1 за старика

4ok commented 9 years ago

Как по мне, то второе условие приводит к излишним зависимостям, каждый блок самостоятелен и сам должен знать как выводиться. А по поводу первого условия - спасибо!

Guria commented 9 years ago

Это уже зависит от контекста задачи и того, что именно делает родительский блок. Родительский блок вполне может знать о дочерних и управлять их выводом. Если же у вас родительский блок достоверно не знает какие блоки в него поместят, то вопрос уже к коду который помещает в родителя блок без данных.

4ok commented 9 years ago

@Guria согласен, что родитель может знать какие блоки в нем должны быть, а какие нет в зависимости от условий. Но ИМХО инкапсулировать условия внутри блоков мне кажется более красивым решением в отличие от кучи условий в самом родителе. Например на странице может быть блок "alert", который выводит сообщения, если они есть например в сессионной переменной или блок "user" с информацией об авторизованном пользователе. Эти блоки могут выводится, а могут и нет, и в даном случае городить кучу условий в блоке родителе смотрится монстрообразно.

qfox commented 9 years ago

@4ok Чтобы не городить условия можно пользоваться модификаторами или кастомными модами. Они нагородят условий за вас.

В любом случае, эти условия где-то надо будет городить — bem-xjst позволяет упростить нагорожение этих условий, а с модификаторами вы их можете еще и по файлам разным разнести.

4ok commented 9 years ago

@tadatuta, почему ты обычно пишешь более длинную конструкцию *.match(function() { return !this.ctx.data; }) вместо более лаконичной *.match(!this.ctx.data)?

qfox commented 9 years ago

@4ok AFAIK короткая до сих пор не работает в dev-mode. Могу ошибаться.

upd Либо, она перестала работать в dev-mode год назад. Как-то так.

4ok commented 9 years ago

У меня все прекрасно работает

blond commented 9 years ago

почему ты обычно пишешь более длинную конструкцию .match(function() { return !this.ctx.data; }) вместо более лаконичной .match(!this.ctx.data)

Такая запись не будет работать, если собирать шаблоны в dev-режиме. Более того, в новых версиях bem-xjst будет ошибка на этапе компиляции, в которой будет сказано, что в данном месте можно использовать только функцию или литерал.

Говоря проще, не оборачивать что-то в функцию можно только, если мы передаём строку, число и прочие литералы, которые не нужно вычислять. Если же мы используем this.ctx, BEM.I18N или что-то ещё, что нужно вычислить, то нужно обернуть это в функцию.

Почему при сборке само всё не обернётся?

В production-режиме всё так и происходит.

А вот dev-режим работает иначе: все исходные файлы просто конкатенируются в один файл и исходный код не подвергаются никакой обработке. Сделано это для удобства отладки.

У меня все прекрасно работает

Это означает, что у тебя используется не самая последняя версия bem-xjst при сборке шаблонов. Ну, и конечно же, сборка в production-режиме.

4ok commented 9 years ago

@andrewblond

blond commented 9 years ago

YENV переменную я при сборке не задаю, соответственно сборка у меня проходит в дев режиме. Верно?

Очень слильно зависит от конкретного конфига, и того, какой тулзой собирать.

В bem-tools для режима сборки BEMHTML обычно использовали переменную окружения BEMHTML_ENV.

В ENB в каждом конкретном случае можно использовать и BEMHTML_ENV, и YENV, и явно указание true или false в конфиге.

bem-xjst где посмотреть какая у меня версия, что это вообще за модуль, я его не нашел

https://github.com/bem/bem-xjst

BEMHTML (тот который из bem-core) написан на bem-xjst. Поэтому инструменты сборки BEMHTML-шаблонов (как в bem-tools так и в ENB) используют bem-xjst для компиляции BEMHTML-кода в обычный JavaScript.

qfox commented 9 years ago

@andrewblond @4ok FYI

Project stub, enb: https://github.com/bem/project-stub/blob/bem-core/.enb/make.js#L60 — сборка шаблонов — BEMHTML_DEV https://github.com/bem/project-stub/blob/bem-core/.enb/make.js#L92 — минификация js/css — YENV

yo bem-stub — та же история, 1в1. недавно сам такой же вопрос задавал, а там 3 независимые переменные окружения используются (третья — бемтри)... С BH все проще, да...

4ok commented 9 years ago

@andrewblond, действительно, у меня стоял старый bem-core, который тянул bem-xjst версии 0.4, в котором отрабатывали короткие конструкции. Спасибо, помог разобраться.