Closed apsavin closed 9 years ago
Вот этот applyAsync не тот же механизм, который ты ищешь?
нет.
Решил задачу, добавив на своем уровне переопределения:
def()(function () {
var content = apply('content');
if (content || content === 0) {
this.ctx.content = apply('', { ctx: content });
}
var js = apply('js');
if (js) {
this.ctx.js = js;
}
return this.ctx;
});
js()(undefined);
Может кто-нибудь прокомментировать, насколько это плохо? Почему бы это не включить в bemtree?
:+1: Насколько я понимаю ситуацию, то если и включать, то в bem-core/i-bem.bemtree
, я лично за, выглядит очень логично. Наверное, надо позвать @veged и @mishanga
@apsavin я не понимаю зачем ты хочешь в шаблоне bemtree для конкретного по моде записывать в js что-то? Мне кажется ты хочешь не правильного.
У тебя же всегда есть какой нибудь блок page.bemtree в котором ты описываешь бэмдерево вот там самое место что бы в bemjson для внутренних блоков описать все что ты хочешь передать в js. Надеюсь я понятно написал)
@voischev я хочу, чтобы блок сам ходил за данными, которые ему нужны.
@apsavin не знаю какая у тебя специфика, но у нас такой подход не очень прижился, потому что получается очень много лишних преобразований и дублирований. В наших проектах удобнее формировать дерево страницы из одного места, ну и соответственно прикидывать нужные данные в блоки из этого же места). У нас одни и те же блоки могут принимать структурно похожие данные из разных мест и кажется очень сложно будет накрутить такую логику внутри блока, который по сути должен будет знать про все приложение, или все возможные варианты использования этого блока, вместо того что бы просто принимать данные и что-то с ними делать внутри.
@voischev у меня есть ощущение, что должно быть два класса блоков: страничные, и обычные. И у страничных можно кроме bemtree, с общей канвой внутренней структуры, описать еще и нодовую технологию, которая будет за данными бегать, а в обычных блоках только bemtree при необходимости, ну или, если блок прям совсем независимый, тоже можно нодовую реализацию. Таким образом у нас получается куча разных типов страниц, описанных страничными блоками, которые знают примерно что в них напихано, и знают чем это рисовать, а дальше логика всем известная: bemtree→bemjson→bemhtml.
upd: т.е., рутовых блоков для bemtree может быть не один, а пачка. А какой из них нужный для конкретной страницы — решится при запуске нодовой технологии. У нас такой подход (на php аналоге node+bemtree) идеально ложится под CMS и нужды.
Я не спорю. Но мне думается что таких блоков не должно быть много :) рутовый блок по дефолтной ноде обычно вернет другой контекст с другим блоком. Вот и для решения этой задачи я бы сделал блок без представления который бы готовил данные для блока который нужно отобразить. Будет выглядить гораздо красивее ;)
// cc @narqo
@apsavin Если я правильно понимаю, то достаточно на своем уровне положить
def()(function() {
this.ctx.js = apply('js');
return applyNext();
});
PS: Для твоей задачи, когда каждый блок ходит за своими данными, обрати внимание на https://github.com/baby-loris/bla — модуль как раз для этого.
@tadatuta То, что ты предлагаешь - это то, с чего я начал, в такой записи apply('js') ничего не возвращает, помогает только редактирование i-bem.bemtree в bem-core так, как я написал выше. Но, может быть, я где-то ошибся, попробую еще раз.
Спасибо за рекомендацию bla
, но у меня уже свой велосипед, который делает примерно тоже самое, но более удобным для меня образом.
@tadatuta Я вчера пытался найти в доке, в тестах что-то похожее, но так и не понял, как это сделать, пока не увидел этих четырех строчек. А кейс, по ощущениям, частый.
Есть же еще вариант реализовывать это через mode('custom-mode')(...)
, верно? Чем он хуже «стандартных» мод типа js
? Почему нельзя доопределить стандартные моды на базовом уровне (или все же можно)? (Имеется ввиду, определение некоегово aria
, например, с последующим использованием aria('flowto')(...);
)
Ощущение, что написано про это много, всё в примерах, но что-то важное упущено.
@apsavin apply('js')
не будет ничего возвращать для случаев, когда на него не написаны шаблоны
надо или добавить к коду @tadatuta
js()(function() { return this.ctx.js })
или делать примерно как в твоём изначальном коде:
def()(function() {
var js = apply('js');
typeof js !== 'undefined' && (this.ctx.js = js); // проверять undefined, чтобы можно было делать block('b1').mod('m1', 'v1').js()(false)
return applyNext();
});
в базовые шаблоны не хочется это выносить, т.к. обычно всё можно сделать в моде def
@zxqfox любые моды до- и переопределяются совершенно консистентно, хоть базовые, хоть кастомные.
и в этом плане пример про доопределение моды content
с вызовом applyNext()
ничем не отличается от аналогичного доопределения дефолтной моды
@tadatuta Вот это как раз и неочевидно. Пример такого рода был бы весьма кстати.
@veged @tadatuta Странно, но предложенные вами варианты не работают. А вот если мой вариант разместить на уровне проекта в i-bem.bemtree - то все ок. Не работают - это значит то, что я передаю в js, игнорируется.
@veged apply('js')
всегда возвращает undefined в случае использования
def()(function() {
var js = apply('js');
typeof js !== 'undefined' && (this.ctx.js = js); // проверять undefined, чтобы можно было делать block('b1').mod('m1', 'v1').js()(false)
return applyNext();
});
и вызывается явно меньшее количество раз. Собственно, видимо, просто не вызывается для того случая, когда я его использую.
@apsavin
я взял project-stub@bem-core
, сделал https://github.com/bem/project-stub/compare/bemtreeJsMode?expand=1 (т.е. ровно такой шаблон, как в твоем комменте, без отдельного объявления моды js
, как рекомендует @veged ) и в результате получаю:
[ { block: 'b1', mods: {}, js: true },
{ block: 'b2', mods: {}, js: { f1: 1, f2: 2 } },
{ block: 'b3', mods: {}, content: 'has no js mode' } ]
Чтобы повторить:
git clone https://github.com/bem/project-stub.git -b bemtreeJsMode test
cd $_
npm i
enb make
node test
@tadatuta
node test
evalmachine.<anonymous>:180
throw e;
^
Error: Match failed
at run (evalmachine.<anonymous>:170:11)
at BEMContext.<anonymous> (evalmachine.<anonymous>:114:14)
at bodyHandler (evalmachine.<anonymous>:92:54)
at apply (evalmachine.<anonymous>:113:40)
at bemApply (evalmachine.<anonymous>:347:20)
at BEMContext.<anonymous> (evalmachine.<anonymous>:558:14)
at run (evalmachine.<anonymous>:173:15)
at BEMContext.<anonymous> (evalmachine.<anonymous>:114:14)
at bodyHandler (evalmachine.<anonymous>:92:54)
at apply (evalmachine.<anonymous>:113:40)
Не может ли быть дело в
echo $BEMTREE_ENV
development
???
@apsavin для dev-режима лечится так:
// i-bem.bemtree на уровне проекта
js()(undefined); // добавилась эта строка
def()(function() {
var js = apply('js');
typeof js !== 'undefined' && (this.ctx.js = apply('js'));
return applyNext();
});
Да, но если использовать дерево
[
{
block: 'b1',
content: {
block: 'b2'
}
},
{
block: 'b2'
},
{
block: 'b3'
}
]
то с моим кодом результат:
[ { block: 'b1',
content: { block: 'b2', mods: {}, js: [Object] }, //ко вложенному блоку применилось правило js
mods: {},
js: true },
{ block: 'b2', mods: {}, js: { f1: 1, f2: 2 } },
{ block: 'b3', mods: {}, content: 'has no js mode' } ]
а с вашим:
[ { block: 'b1',
content: { block: 'b2', mods: {} }, // вложенный блок остался без js
mods: {},
js: true },
{ block: 'b2', mods: {}, js: { f1: 1, f2: 2 } },
{ block: 'b3', mods: {}, content: 'has no js mode' } ]
@apsavin, действительно, applyNext()
выставляет защиту от зацикливания в виде поля в this
. И т.к. this
общий для всех потомков, то вглубь по дереву шаблон больше не матчится.
Угу, видимо, придется оставить мой вариант, с некоторым дублированием кода из i-bem.bemtree в bem-core
Привет.
Я тут думаю, как бы мне так доопределить bemtree, чтобы можно было писать
и
вместо
Может, кто-то уже делал такое?