Closed KlonD90 closed 9 years ago
Если я правильно понял, то:
// первый раз:
if (!this.elem('your-elem')) {
DOM.update(
this.domElem,
BEMHTML.apply({ block : 'your-block', elem : 'your-elem', content : 'your-content' })
);
this.dropElemCache('your-elem');
}
this.elem('your-elem').html('asdasdasdasd');
Если нужно генерировать блок динамически:
var bHtml = BEMHTML.apply({ block : 'your-block', content : 'your-content' });
var initedBlock = BEMDOM.init($(bHtml));
Послать событие:
initedBlock.emit('sobytie');
Про попапы. Судя по всему, упущен следующий момент:
BEMDOM.decl('popup', {
onSetMod : {
'js' : function () {
this.__self.popups.push(this); // сохраняем инстанс
}
},
close : function () {
// закрываем попап
}
}, {
popups : [],
close : function () {
this.popups.forEach(function (el) { el.close(); });
}
});
Вроде, не сильно наврал ;)
Спасибо, со статическим методом понял момент :) Вот что-то не сильно работает такой способ брать динамически объект. После init он возвращает просто jQuery объект, видимо придется сделать через этот статический способ чтобы его получить или есть какой-то метод получше?
@KlonD90 Получить инстанс БЭМ-блока в примере от @zxqfox можно так:
var bHtml = BEMHTML.apply({ block : 'your-block', content : 'your-content' });
var initedBlock = BEMDOM.init($(bHtml));
var yourBlock = initedBlock.bem('your-block');
Еще можно использовать findBlock*
-методы и передать им в качестве контекста jQuery-chain, который вернется из init()
.
Но вообще мне кажется, что исходную задачу нужно решать чуть по-другому. Вместо того, чтобы вставлять блок в DOM на первое обращение, потом находить и обновлять на последующие, лучше изначально вставить его в DOM, но инициализировать в момент первого обращения и дальше обновлять. И API прямее получится и лишних депендов на клиент не тянуть и кода меньше писать ;)
@tadatuta Спасибо, так заработало :)
Было бы круто так сделать, но как это сделать не порождая какой-то скрытой зависимости? Так чтобы по условию если эта библиотека есть в депсе то в body вставлялся блок куском хтмля с указанием того чтобы он относился к этому блоку?
@KlonD90 Я бы сделал так (и кажется, что @tadatuta предлагает примерно тож самое):
[
...,
{ block : 'your-hidden-block' }
...
]
.your-hidden-block { display : none }
.your-hidden-block_js_inited { display : block }
// ...
BEMDOM.decl('your-hidden-block', {
onSetMod : {
'js' : function () {
// initialization
console.log('inited');
}
}, {
live : true
});
inited в этом случае выведется только тогда, когда кто-то явно позовет твой блок. Например, $('.your-hidden-block').bem('your-hidden-block')
.
p.s. Я не знаю, используешь ли ты bem-core с модулями, или i-bem без всего, поэтому не заворачивал в модули. Если используешь, то чтобы получить $ нужно будет пример выше завернуть в modules.require(['jquery'], function ($) { ... });
, и блок с BEMDOM в modules.define('your-hidden-block', ['i-bem__dom'], function (provide, BEMDOM) { provide(BEMDOM...); });`
@tadatuta спасибо за правку, забыл, что DOM.init возвращает jquery-chain.
По поводу
Так чтобы по условию если эта библиотека есть в депсе то в body вставлялся блок куском хтмля с указанием того чтобы он относился к этому блоку?
Не очень понятно, в каком именно депсе он может быть. Если в том депсе, что собирается из bemjson — то вариант из предыдущего сообщения. Если в каком-то другом — то у тебя уже зависимость от этого блока ЯВНО описана и вставить твой блок можно в том блоке, который его просит, и «не порождая какой-то скрытой зависимости» при этом соблюдается.
Для второго варианта можно вставить, например, через доопределение page. Для этого мы в page.bemhtml
или page.bh
(в зависимости от того, что у тебя используется) должны будем на уровне проектный блоков описать шаблоны примерно такого толка:
block('page').content()([
applyNext(), // или applyCtx?
{ block : 'your-hidden-block' }
]);
или в bh:
module.exports = function(bh) {
bh.match('page', function (ctx) {
ctx.content([
ctx.content(),
{ block : 'your-hidden-block' }
]);
});
};
При этом css
и js
можно взять из предыдущего примера.
@zxqfox Спасибо :) Хочется выработать подход какой-то правильный, а если его вставлять в каждый блок то не получится синглтон. Ну в принципе да видимо сделаю так что вставлю в page, а потом .bem инициализирую.
@KlonD90 Я честно не очень понял что именно ты хочешь, но еще есть вариант сделать этот блок, например, элементом page или просто слушать события на page, и инициализировать блок по событиям на page. Хотя, на мой взгляд это мало чем отличается от blocks['your-hidden-block'].staticMethod()
в котором ты свой блок и позовешь, а он инициализируется, если надо, и сделает что нужно.
Здравствуйте. Хочу сделать сервисный блок, чтобы блок фактически генерил только один элемент и при повторном обращение его просто обновлял, но генерил эту штуку только если его вообще потребовали. Столкнулся с проблемой, что я без понятия как засейвить этот элемент и как с ним правильно обращаться. В сам по себе блок не хочется вставлять эту логику, так что синглтонизацию вынес в отдельный модуль, он инитится(я пользуюсь bem-stack'ом и инитится он i-bemdom) и выводится, но как его дальше взять я без понятия, и как послать событие от моего модуля к таким образом сгенеренному блоку тоже без понятия. Помогите плиз ._.
И еще вопрос в догонку есть ли какой-то cheatsheet с шаблонами реализации для i-bem. И еще один вопрос в http://ru.bem.info/technology/i-bem/v2/i-bem-js/ тут написано Пример: Вызов статического метода close блока popup — закрыть все попапы на странице: можно полностью этот пример, а то я пытался как-то реализовать, но если метод статический то никакой this.delMod('visible') не сработал и что либо еще не смог сделать с объектом, нужно видимо еще какие-то настройки в случае объявление такого делать, можно их привести полностью и сам метод close?