Ребята, помогите собрать JS-блока.
Цель: 1) Получить реализацию блока в технологии JS 2) Получить минимум знаний по JS в методологии БЭМ, для дальнейшего +/-самообучения
Исходные данные:
- Блок sitemap, элемент button__icon_close
- Блок button с миксом menu__button, блок расположен вне блока sitemap
- Знание JS - ноль.
- Знание ООП - поверхностное на уровне новичек, язык с#
- Структура файлов:
BEMJSON:
{
block: 'sitemap',
js : true,
content: [
{
block: 'button',
mix : { block : 'sitemap', elem : 'button' },
attrs : { title : 'Закрыть меню' },
icon: {
elem: 'icon',
tag: 'span',
elemMods: {close: true}
}
}
]
},
{
block: 'button',
mix: {block: 'menu', elem: 'button', theme: 'menu'},
url: '#',
title: 'Открыть меню сайта',
content: 'Меню',
tabIndex: 2
}
Поиск решения:
Первое что попробовал - вывести лог при клике.
modules.define(
'sitemap',
['i-bem-dom'],
function(provide, BEMDOM) {
provide(BEMDOM.decl(this.name, {
onSetMod : {
js : {
inited : function () {
this.bindTo('click', function () {
console.log('click');
})
}
}
}
}));
});
Консоль браузера сразу заругалась:
jQuery.Deferred exception: i.decl is not a function TypeError: i.decl is not a function
at Object.<anonymous> (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:35:58)
at http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1662
at c (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1009)
at R (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1792)
at http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1641
at HTMLDocument.<anonymous> (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:2:8353)
at j (https://yastatic.net/jquery/3.1.0/jquery.min.js:2:29568)
at k (https://yastatic.net/jquery/3.1.0/jquery.min.js:2:29882) undefined
r.Deferred.exceptionHook @ jquery.min.js:2
k @ jquery.min.js:2
jquery.min.js:2 Uncaught TypeError: i.decl is not a function
at Object.<anonymous> (index.min.js:35)
at index.min.js:1
at c (index.min.js:1)
at R (index.min.js:1)
at index.min.js:1
at HTMLDocument.<anonymous> (index.min.js:2)
at j (jquery.min.js:2)
at k (jquery.min.js:2)
в шапке модуля меняю i-bem-dom на i-bem__dom, консоль без ошибок, как и без ожидаемого console.log
Пока в ступоре, и вопросов немного: 1) В чем может быть ошибка, этого простого кода? 2) Как подписаться на событие click блока button, который вне блока sitemap?
this.bindTo
— это методi-bem__dom
из предыдущей версииbem-core
. Начиная сv4.0.0
элементi-bem__dom
был превращен в самостоятельный блокi-bem-dom
и поменялась работа с событиями.Отличия между версиями описаны в миграционном гайде: https://ru.bem.info/platform/libs/bem-core/4.1.1/migration/ Про причины изменений рассказывал @veged на Я.Субботнике: https://events.yandex.ru/lib/talks/3685/
В «современном» мире вызвать
console.log()
по клику наsitemap
можно так:Чтобы в целом ознакомиться с использованием
i-bem.js
рекомендую https://ru.bem.info/platform/i-bem/Спасибо...
Получается документация https://ru.bem.info/platform/i-bem/ - не актуальна!?
Блин.. я же всё о i-bem.js распечатал - целую книжку :D
@tadatuta недавно решали подобную задачу - закрытие окна(modal) по нажатию крестика (modal__close):
Как удалить модификатор у блока - sitemap_visible, по нажатию крестика - button__icon_close ? здесь модификатор, в примерах не увидел подобного...
Свежак выкатили 2 февраля.
31 января распечатал - промазал в пару дней >D
https://ru.bem.info/forum/1245/#comment-277466329 - еще нужна помощь
Как всегда, это можно сделать по-разному. Хороший вариант — в блоке
sitemap
подписаться на клик по кнопке (событие всплывет наверх).При этом, чтобы отличить кнопку-закрывашку от остальных кнопок, к ней можно примиксовать элемент блока
sitemap
.В JS коде для элемента подписываться на БЭМ-событие
click
у блокаbutton
и эмитить собственное событие клик. Тогда на него можно будет подписываться сlazyInit
.Ну т.е. идея очень похожая на то, что сделано для закрытия
modal
, с тем лишь отличием, что в элементеclose
блокаsitemap
вместо подписки на DOM-событие будет подписка на БЭМ-событие блокаbutton
:Если же экономить чернила и забить на ленивую инициализацию, то можно обойтись просто
но лучше не экономить ;)
Правильно ли я понимаю- что, привязываться к модификатору элемента закрывашки не стоит (если это вообще возможно) ?
В смысле к модификатору блока
button
? Не стоит, т.к. этот модификатор не имеет прямого отношения к блокуsitemap
. Идея в том, что элементsitemap__close
может быть реализован через что угодно: самостоятельно, через блокbutton
с или без модификатора или вообще через какой-то другой блок, поэтому завязка на свой элемент всегда надежнее и гибче.Но, разумеется, если обсуждать вариант, как решить задачу за минимум символов кода, то многое можно сократить в ущерб надежности и расширяемости. В т.ч. отказаться от отдельного элемента для закрывашки, отказаться от ленивой инициализации и тогда можно подписаться непосредственно на найденный внутри блок
button
с нужным модификатором.Код из комментария -https://ru.bem.info/forum/1245/#comment-277467485 modules.define('sitemap__close', ['i-bem-dom', 'button'], function(provide, bemDom, Button) {
}); Есть вопросы: 1) При сборке Gulp выдает ошибку, лог: [10:48:35] 'build' errored after 5.75 s [10:48:35] GulpUglifyError: unable to minify JavaScript Caused by: SyntaxError: Unexpected token punc «(», expected punc «:» (line: 6, col: 14, pos: 194)
минификатор JS ругается чего-то
2) 7я строка: events или _events ?
3) При попытке вывести console.log по клику, ни чего в консоле не произошло. Как понять что код работает?
onInit() {
->onInit: function() {
_events
, опечатался._events
у меня выводится, сделал веточку: https://github.com/bem/project-stub/tree/issues/1245Дублирую сюда gulpfile крушит JavaScript с данным конфигом. Не разобрался, но именно замененный gulpfile (с моего проекта) крошил выполнение js в sitemap__close
Вроде разобрался. Скорее всего проблема была в отсутствии плагина "gulp-if"
Установка данного плагина, разрешила прошлую проблему:
Минификатор не ругается, ES6 синтаксис - ни при чем оказалcя
Данный модуль, пока не может удалить модификатор visible
Вопросы по решению: 1) Нужно ли писать отдельный модуль для блока sitemap в этом же файле? 2) Если не нужно то каким образом удалить модификатор? Ведь везде стоит this (sitemap__close), и логично что this.delMod('visible'); - должен удалить модификатор на себе, а не на родителе.
ES6 по-прежнему будет падать при сборке в продакшен-режиме (когда будет запускаться
uglifyJS
. Просто в недавнем обновленииgulp
конфига вproject-stub
как раз добавилось разделение на режимы, что в девелопменте сборка происходила шустрее: https://github.com/bem/project-stub/pull/232Предполагалось, что да — нужно создать JS-реализацию блока
sitemap
, поймать всплывшее событие и там удалить модификатор. Но как всегда в случае экономии кода можно чуть сократить и воспользоваться тем фактом, что у элементов есть ссылка на родительский блок:this._block
.В консоли получил VisibleClose. Значит удалил бы модификатор у
sitemap__close_visible
, если бы такой элемент существовал. Но существует только -sitemap_visible
.this._block.delMod('visible');
- не помогает, консоль ругается - delMod не является функцией. Ну это и понятно. Пробовал даже -this.findParentBlock(sitemap).delMod('visible')
- то же не знает такого блока, т.к. находимся в элементеsitemap__close
. В ступоре. Вот - не хватает пару пазлов в голове, что бы прояснить взаимодействие блоков!P.S. Прошу не материть, первые шаги в JS
Про
_block
я неправильно подсказал — это не свойство, а метод. Так что работающий вариант выглядит так:Ну а если «по полной программе», то как-то так:
ЗАРАБОТАЛО!!! УРА
Володя спасибо. ))))
Примерно понятно куда смотреть далее. Пойду открывашку оживлять .
Круто, сам на днях попал, разбираясь почему не происходит инициализация (в документации был старый пример с
i-bem__dom
).Там раздел коллекций не открывается.
Вопрос:
проще: можно ли подписаться на БЭМ-событие элемента footer__call который в футере, из Блока Хэдер?
Как это сделать? Вообще это возможно?
@rteamx
Спасибо, исправил: https://github.com/bem-site/bem.info/pull/156 Завтра появится на сайте.
@DjonyBastone
Вариантов несколько:
page
. При этом нужно понимать, что элементы для того и задуманы, чтобы скрывать детали реализации блока от внешнего мира и если возникает необходимость подписаться на событие элемента, по-хорошему нужно сначала поймать событие элемента из его блока и там сгенерировать событие уже от лица самого блока.Первый вариант кажется наиболее подходящим в данном случае.
код работает.
Структура блока
'header'
Необходимо установить модификатор
'visible'
- вложенному блоку'sitemap'
Мне кажется должно быть аналогичное решение:Как из родителя назначить модификатор блоку?
Так тоже не работает((
Как из родителя назначить модификатор блоку?
Народ. Оформил первый в жизни JS с вашей помощью. Кое-что сам додумал. Пожалуйста посмотрите gist сориентируйте. что не так, что можно улучшить..
https://gist.github.com/DjonyBastone/80efa9c80f713e479b9b04b6e49ffb8e
Нужна обратная связь
https://ru.hexlet.io/courses/programming-basics буквально за неделю будет выше нуля
@Il'yar спасибо, очень кстати.
Цель просмотра вами кода в гист (https://ru.bem.info/forum/1245/#comment-278247503) - оценка "БЭМ/неБЭМ" и что можно улучшить..
Если кто-то даст обратную связь, буду рад.
По гисту сильно не всматривался, вижу несколько очевидных рекомендаций:
@DjonyBastone Есть встречное предложение.
Надо сделать PR решающий этот запрос https://github.com/ilyar/bem-examples/issues/1
Польза: практика использования БЭМ-стека; максимум обратной связи "БЭМ/неБЭМ".
cc @frimen cc all
Пример одного PR, чтобы уловить суть момента, надо проследить все комментарии их всего 21 (https://github.com/bem/project-stub/pull/39).