Open adinvadim opened 8 years ago
@adinvadim
bem-xjst
работает таким образом, что если поле block
не задано явно, то оно обязано быть достроено из контекста. И если текущий контекст оказывается wrapper-block
, то остается лишь явно задавать нужный блок самостоятельно.
Другое дело, что это можно очень по-разному выразить в коде. Например:
[
{
elem: 'media',
urls: data.links,
},
{
elem: 'content',
content: [
{
elem: 'title',
content: data.title
},
{
elem: 'description',
content: data.description
}
]
}
].map(function(item) {
item.block = this.block;
return item;
}, this);
Либо вместо оборачивания в wrapper-block
завернуть в video__inner
, смиксованный с wrapper-block
, тогда сохранится контекст video
.
О, с video__inner и правда крутое решение, спасибо! А еще такой вопрос, у меня многие блоки могут иметь или не иметь обертку wrapper-block
и поэтому у многих пристуствует такой код, можно как-нибудь избежать большого повторения кода и написать что-то типа wrapped()(true)?
def()(
match(function() { return !this.ctx._wrapped })(function() {
this.ctx._wrapped = true
return applyCtx({ block: 'wrapper-block', content: this.ctx })
})
),
Для оборачивания из коробки есть хелпер:
block('b1').wrap()(function() {
return {
block: 'wrapper-block',
content: this.ctx
};
});
Это отвечает на вопрос или хочется чего-то другого?
Ого, круто, а много еще подобных хелперов, которых в доках нет, или я где-то не досмотрел?
Хочется уметь самому хелперы писать, где можно про это почитать?
Есть еще replace()
для замены блока новым деревом (чаще пригождается в BEMTREE):
block('b1').replace()(function() {
return [{ block: 'b2' }, { block: 'b3' }];
});
По поводу своих хелперов. Есть два варианта: положить хелпер в this
(будет доступен из всех блоков) или написать кастомную моду для селектора на *
:
// добавляем хелпер в this
oninit(function(exports) {
exports.BEMContext.prototype.someHelper = function() {
// ...
};
});
// использование
block('b1').content()(function() {
return 'blah' + this.someHelper();
});
// кастомная мода для любых блоков
block('*').mode('someMod')(function() {
return 'something';
});
// ее можно звать вручную, когда реально требуется или дергать из `def()` автоматически для всех:
block('*').def()(function() {
apply('someMod');
return applyNext();
});
:fire: Спасибо большое за развернутый ответ!
у меня с этой проблемой появился еще один кейс, и не могу пока что найти нормальное решение
есть струкура:
.block (+ модификаторы)
...
.block__preview
.block__overlay
.block__image
...
Потом bemhtml оборачивает block__preview в блок link из bem-components, и соотвественно меняется контекст дальше и получается такой результат
.block (+ модификаторы)
...
.link
.link__preview
.block__overlay
.block__image
...
block: this.block
решает только ряд проблем, потому что помимо поля block в контексте изменилось еще поле mods
block: this.block
и mods: this.mods
решает проблемы, но это плохое решение, так как все модификаторы выставляются на элементы, что немного странно, по идеи чтобы повесить модификатор на элемент, нужно воспользоваться elemMods
и получается что-то типо этого:
.block (+ модификаторы)
...
.link
.block__preview (+ модификаторы блока block)
.block__overlay
.block__image
...
Возможно тут как-то можно доопределить шаблон link, но у меня идей нет
Можно явно сбросить mods
в undefined
.
Но точно ли нужна такая «магия» внутри BEMHTML? Я бы предложил строить полное дерево уже на этапе BEMTREE, а для BEMHTML оставить чисто «визуальные» штуки: кому какой тег задать, атрибуты и т.п.
PS: относительно контекстное обсуждение сегодня: https://github.com/bem/bem-forum-content-ru/issues/848 (в комментариях есть вариант решения с wrap()
).
Я бы в данном случае скорее сделал бы шаблон для media-item__link
копипастом из link
(к нему, если нужны стили link
, можно добавить микс с link
). Тогда контекст сохранится.
Кмк, это будет меньшим из зол.
На выходе после BEMTREE шаблонизации выходит примерно такой bemjson
Элемент
__media
с помощью bemhtml потом оборачивается в блокwrapper-block
Что нужно написать в блокеwrapper-block
, чтобы он не менял в контексте block, чтобы не делать вот так: