bem-site / bem-forum-content-ru

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

Не явное поведение mods в BEMHTML #736

Closed voischev closed 8 years ago

voischev commented 8 years ago

Поиграться можно тут http://bem.github.io/bem-xjst/

Пара типов данных

({
    block: 'block1'
});

или

({
    block: 'block1',
    mods: { a: 'b' }
});

Далее буду приводить по паре шаблонов где можно отсмотреть разное поведение при разных условиях и при этом ожидание результата не оправдывается

Вариант 1 (как бы правильный)

block('block1')(
    def()(function() {
        this.mods.bla = 'bla';
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

вариант 2

block('block1')(
    def()(function() {
        this.mods = { bla: 'bla' };
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Вариант 3

block('block1')(
    def()(function() {
        this.ctx.mods = { bla: 'bla' };
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Вариант 4! Причем работает как нужно есть есть mods в bemjson

block('block1')(
    def()(function() {
        this.ctx.mods.bla = 'bla';
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Еще их вариации

Что интересно даже

block('block1')(
    def()(function() {
        this.mods = this.extend(this.mods, { bla: 'bla' });
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Не работает как нужно. Ожидаю что как бы я не записал модификаторы (через создание нового объекта или через ссылку. через this.mods или через this.ctx.mods) то отработают шаблоны по ним и классы будут в результате шаблонизации.

Вероятно дело в том что когда в mods пишешь новый объект ссылки теряются по этому то шаблон BEMHTML не отрабатывает то класс не проставляется в результате шаблонизации. Не доконца ясна в таком случае ситуация с this.mods и this.ctx.mods

Как это объясняется вами? И что делать? Что будет делаться если будет?

voischev commented 8 years ago

ping @tadatuta @vithar @veged

tadatuta commented 8 years ago

Историческая подоплека: если для некоторого блока написаны шаблоны для какого-то модификатора, то потенциально есть два варианта ожидаемого поведения:

  1. Добавить модификатор так, чтобы на блоке появился нужный класс, но не применились шаблоны этого модификатора
  2. Чтобы шаблоны модификатора тоже отработали.

Кроме того, иногда нужно знать, какие модификаторы были заданы в BEMJSON, а какие были добавлены в рантайме из шаблонов.

this.ctx.mods — это значение модификаторов, изначально переданное в BEMJSON. Его изменение приводит лишь добавлению классов. А изменение this.mods приведет к применению шаблонов на вновь выставленные модификаторы.

voischev commented 8 years ago

С этим все понятно. Что делать с ссылками или добавлением нового объекта? Потому что поведение явно требует либо доработки или пояснения как с этим жить всем. Потому что даже с этой "исторической подоплекой" модификаторы работают по прежнему так же неожиданно. :)

tadatuta commented 8 years ago

Ну так со ссылками ты сам же и написал про причины.

Я бы предложил всегда использовать такой способ досыпания модификаторов в рантайме:

block('b1').def()(function() {
    return applyNext({ mods: this.extend(this.mods, { m1: 'v1', m2: 'v2' }) });
});

А от всех прочих вариантов просто отказаться.

voischev commented 8 years ago

@tadatuta О! Спасибо! Годиться!

voischev commented 8 years ago

@tadatuta правда что-то в enb-bemxjst@next пакете такое не прокатило :-( Остается по ссылкам работать.

veged commented 8 years ago

вообще, для случая, когда нужно просто добавить класс, я бы рекомендовал использовать mix а не трогать ни this.mods ни this.ctx.mods (которые вообще-то должны ссылаться на один и тот же объект)

voischev commented 8 years ago

@veged для такого простого случая так и делаем ;)