Есть у меня значит такая страктура:
blockA - подписывается как liveBindTo на change от инпута. Внутри по change эмитим событие change наверх. blockB - более высокоуровневый, работает с blockA. Делает this.liveInitOnBlockInsideEvent('change', 'blockA', function(e) { /* тут эмитим событие наверх this.emit('toggle'). Вот здесь я вылетаю каждый раз / }) blockC - еще более высокоуровневый. Работает с blockB. Делает this.liveInitOnBlockInsideEvent('toggle', 'blockB', function(e) { / И здесь тоже. */ })
По сути получается, когда я кликаю на чекбокс (blockA) и вот это вот все эмитит события на верх, оно пытается проинициализироваться на каждый следующий клик (change/toggle) хотя все блоки заинитились (blockA, blockB, blockC).
Пока залепил булевым локом на инстанс. Но ведь негоже.
Погоди, liveInitOnBlockInsideEvent вызывается несколько раз или колбек события change?
Вроде бы, все работает и как должно.
p.s. liveInit нужен чтобы создавать экземпляр для блока не при загрузке, а при каком-то событии, и заодно обработчик на это событие описывать.
Callback, который был передан в
liveInitOnBlockInsideEvent
вызывается несколько раз (точнее, каждый раз, как возникает событие в блоке, который я отслеживаю).Ну я так и использую. Иничу вышестоящие блоки только если самый нижестоящий стриггерил
change
Значит, все работает правильно, так и задумано ;-)
liveInitOn...Event
это что-то:Такое ;-) Точнее, через $('body').delegate, или как там у jquery.
Вот у меня примерно так выглядит blockC:
И вот так blockB:
Т.о. я лениво инициализирую блоки
blockB
иblockC
по событиюchange
отblockA
. Т.е. я правильно понимаю, чтоthis._liveInited
мне здесь необходим и это так и задумано?UPD:
Как то странно получается, в документации на
liveInitOnBlockInsideEvent
написано: https://en.bem.info/libs/bem-core/v2.8.0/desktop/i-bem/jsdoc/#jsdoc-liveInitOnBlockInsideEvent-1Но ведь блок то у меня уже инициализирован (blockA который) а обработчик
liveInitOnBlockInsideEvent
на блоке blockB вызывается каждый раз.@korotovsky Приведи, пожалуйста, исходную задачу целиком.
Ну смотри...
https://ru.bem.info/technology/i-bem/v2/i-bem-js-init/#Хелперы-для-инициализации-по-событию
@tadatuta я же не путаю?
Ну задача следующая: инициализировать ленво бизнес блок (blockC) только когда было какое-либо взаимодействие с блоком blockB (грубо говоря с блоком blockA).
Почему лениво - потому что эта таблица, и в ней дохерищща чекбоксов. Каждый чекбокс представляет из себя "капусту" из blockA -> blockB -> blockC.
А вот это как мне кажется надо жирным в доке написать, т.к. имхо текущее поведение не отражает то, что там написано в описании. Ну, как мне кажется.
Сильно понятнее не стало, но @zxqfox все правильно написал — инициализация блока произойдет ровно один раз, а коллбек в
liveInitOnBlockInsideEvent
будет дергаться каждый раз, когда будет случаться указанное событие.Проверить это очень просто:
Но я все еще не понимаю подробности задачи — всю эту историю с перекидыванием событий внутри. У меня есть смутное подозрение, что там можно все заметно упростить.
Можешь переформулировать не в терминах «хочу лениво инитить блок, ловить событие, снова кидать событие и на него подписываться», а в терминах верхнеуровневого техзадания, вроде «хочу, чтобы при клике на чекбокс внутри таблицы выполнилась такая-то сложная логика»? А я попробую посоветовать оптимальное решение.
В терминах верхнеуровнего техзадания: хочу чтобы при клике на чекбокс в таблице его значение появлялось в шапке. И так для всех чекбоксов из таблицы. Чекбоксов там 2 класса (одного типа и другого.) грубо говоря при клике на один тип надо чтобы значение в шапке было зелёное, а на другой - красного.
Сам модуль чекбокса должен быть как переиспользуемый компонент. Т.е. ни о каких классификациях типа красный или зелёный знать не должен.
Чекбоксов в таблице может быть хоть 100 штук.
Предложу такой вариант https://github.com/bem/project-stub/commit/11da366c6fdd85e66b599a8b52f0c16aa80a680b Или, если есть гарантия, что никаких других чекбоксов в
app
быть не может, то можно сократить до https://github.com/bem/project-stub/commit/427506478b3c9559f8e5ed19ad47029ae71621c4Само собой, что вместо общего родителя может быть медиатор (например, на основе events__channels), а знание о типе чекбоксов вместо модификатора могут хранить js-параметры или микс с соответствующим элементом.
Подходит?
Если честно, в твоем примере убрана половина из того, что мне необходимо в задаче ) Например чекбокс у меня это композиция блоков
b-form-input
иb-form-checkbox
.Конечно гарантии нет! Это же не project-stub у меня.
Так и сделано (на блоке
blockC
)Он тоже уже запилен в виде хэлпера-враппера к
events__channels
.Поэтому, если честно, не вижу принципиальной разницы между твоей и моей реализацией.
А, еще на сколько я понял блок
app
у тебя не ленивый, поэтому он слабо стыкуестя с моим блокомblockC
. В моем случае таких блоков может быть более ста, как если бы у тебя была сотня блоковapp
.Я потому и прошу полное понятное описание задачи, чтобы придумать решение к нему. Условия, которые были описаны в предыдущем комменте, у меня выполняются ;) Насыпь подробностей — попробую подобрать решение с их учетом.
Да я думаю это не требуется, в принципе я понял какие пути есть для достижения моей цели.
Кстати вот снова, к.м.к неконсистенция, воспользовался методом
liveInitOnEvent
и вот его коллбэк вызывется всего 1 раз. А уliveInitOnBlockInsideEvent
каждый раз. Хотя из описания это вообще не следует:vs
Резюмируя, мне кажется, что поведение у
liveInitOnEvent
более логичное и предсказуемое.