До сих пор не могу понять магию apply
, applyNext
, applyCtx
хотя ни раз читал ман по ним
Вообще мне нужно изменить элемент на ссылку, если в параметрах есть url, я сделал так
block('nav').elem('item')
(
match(this.ctx.url)
(
function()
{
this.ctx.block = 'link';
delete this.ctx.elem;
this.ctx.mix = [
{
block: this.block,
elem: 'item'
}
];
applyCtx(this.ctx);
}
)
);
Получаю бесконечную рекурсию - [RangeError: Maximum call stack size exceeded]
Сейчас я поставил такой костыль:
block('nav').elem('item')
(
match(this.ctx.url && !this.ctx._prepared)
(
function()
{
this.ctx.block = 'link';
this.ctx._prepared = true;
delete this.ctx.elem;
this.ctx.mix = [
{
block: this.block,
elem: 'item'
}
];
applyCtx(this.ctx);
}
)
);
Как сделать правильно?
На сколько я знаю с рекурсией обещали разобраться в следующих релизах. А пока про такой костыль где то даже в доках было написано
вообще должно работать как-то так:
я добавил
.def()
(именно в шаблонах по дефолтной моде имеет смысл применятьapplyCtx
) и немного исправил логику с редактированием контекста прямо inplace (так не стоит делать, потому что BEMJSON API блока и элемента могут не совпадать и лучше явно создавать блок)Также было замечено, что applyCtx по дефотной моде не вызывало проблем, на как только захотелось использовать match условие, появилась рекурсия, спасибо за подсказку использования def и match вместе, завтра попробую этот вариант и отпишу
Не очень понял смысл фразы "так не стоит делать" в контексте. Не стоит делать как было написано у меня из-за того что api блока и элемента может не совпадать, правильно я понял?
Что почитать, чтобы наконец понять как работают методы apply, а то пишу больше на интуиции, пробуя разные варианты. Может это относится к xslt и его почитать или что?
Например ты написал, что applyCtx работает с дефолтной модой, а где это можно прочитать?
У меня сложилось впечатление, что отличие applyNext от applyCtx лишь в том, что аpplyNext работает с текущим this, а applyCtx с тем, что ему передали в виде аргумента. Еще заметил много где пишут return applyNext, хотя он ничего не возвращает
Я на интуиции написал больше трех проектов)) значит в правильно делаешь)
@4ok попробуй скомпилить пустой шаблон, в коде можно покопаться и разобраться :) Я так делал в https://github.com/alexbaumgertner/bare-bemhtml/blob/master/bare-bemhtml.js :)
Например, можно увидеть, как сохраняется контекст https://github.com/alexbaumgertner/bare-bemhtml/blob/master/bare-bemhtml.js#L391 а
apply
по сути – это вызов функции, возвращающей шаблонизированные данные https://github.com/alexbaumgertner/bare-bemhtml/blob/master/bare-bemhtml.js#L18А если смотреть исходниики не компилированные, то вот
def() https://github.com/bem/bem-core/blob/v2/common.blocks/i-bem/i-bem.bemhtml#L322
Вот вызов стандартных мод https://github.com/alexbaumgertner/bare-bemhtml/blob/master/bare-bemhtml.js#L56-L121
В общем, посмотрите свой скомпилированый bemhtml, можно для удобочитаемости прогнать через http://jsbeautifier.org
попробуйте bh, он кажется немного проще
Где почитать bh?
https://github.com/enb-make/bh
Срезюмирую про apply*.
apply
,applyNext
иapplyCtx
— это синтаксические конструкции, первые две относятся кxjst
, третья кBEMHTML
. Разница между ними следующая:apply
. ВapplyNext
автоматически выставляется защита от зацикливания, так что вы гарантировано не вернетесь в этот же шаблон.applyNext
, где по пустой моде вthis.ctx
присваивается объект, переданный в качестве параметра.Соответственно
apply
практически не нужен никогда,applyNext
используется тогда, когда вы хотите получить предыдущий результат работы этого шаблона, аapplyCtx
нужен тогда, когда вы хотите заиспользовать новый кастомный, динамически сгенерированныйbemjson
.Об этом хорошо написано в Референсе по BEMHTML.
Написал, что происходит в моде
def
https://github.com/bem/bem-core/issues/643