Хочу начать использовать БЭМ в своём небольшом проекте. Переписывать весь html через bemhtml как-то совсем не интересно.
Существует ли какая-то более простая замена, в основе которой будут обычные html-файлы c декларациями блоков? Как-то так:
Хочу начать использовать БЭМ в своём небольшом проекте. Переписывать весь html через bemhtml как-то совсем не интересно.
Существует ли какая-то более простая замена, в основе которой будут обычные html-файлы c декларациями блоков? Как-то так:
Есть такая структура:
desktop.blocks
input
__control
input__control.bemhtml
input__control.styl
input.bemhtml
input.styl
desktop.bundles
index
index.bemjson.js
При запуске сервера "./node_modules/.bin/bem server", генерируется файл index.bemdecl.js, но он не содержит элементы блока input, а добавляет только это:
...
{
"name": "input"
}
...
Проект создавал с помощью bem-stub: bem-toos, bem-core.
make.js:
/* global MAKE:false */
// process.env.YENV = 'production';
var PATH = require('path');
require('bem-tools-autoprefixer').extendMake(MAKE);
MAKE.decl('Arch', {
blocksLevelsRegexp: /^.+?\.blocks/,
bundlesLevelsRegexp: /^.+?\.bundles$/
});
MAKE.decl('BundleNode', {
getTechs: function () {
return [
'bemjson.js',
'bemdecl.js',
'deps.js',
'stylus',
'css',
'bemhtml',
'html'
];
},
getForkedTechs: function () {
return this.__base().concat(['stylus']);
},
getLevelsMap: function () {
return {
desktop: [
'libs/bem-core/common.blocks',
'libs/bem-core/desktop.blocks',
'libs/bem-grid/common.blocks',
'common.blocks',
'desktop.blocks'
]
};
},
getLevels: function () {
var resolve = PATH.resolve.bind(PATH, this.root),
buildLevel = this.getLevelPath().split('.')[0],
levels = this.getLevelsMap()[buildLevel] || [];
return levels
.map(function (path) { return resolve(path); })
.concat(resolve(PATH.dirname(this.getNodePrefix()), 'blocks'));
},
'create-css-node': function (tech, bundleNode, magicNode) {
var source = this.getBundlePath('stylus');
if (this.ctx.arch.hasNode(source)) {
return this.createAutoprefixerNode(tech, this.ctx.arch.getNode(source), bundleNode, magicNode);
}
}
});
MAKE.decl('AutoprefixerNode', {
getPlatform: function () {
return this.output.split('.')[0];
},
getBrowsers: function () {
var platform = this.getPlatform();
switch (platform) {
case 'desktop':
return [
'last 2 versions',
'ie 10',
'ff 24',
'opera 12.16'
];
}
return this.__base();
}
});
Читаю задачу-пример из документации, вот ссылка на задачу https://ru.bem.info/technology/bemhtml/2.3.0/reference/#%D0%92%D1%8B%D0%B1%D0%BE%D1%80-%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D0%B0-%D0%B2-%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8-%D0%BE%D1%82-%D1%80%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%BE%D0%B3%D0%BE-%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%B0 не могу никак понять следующие моменты: 1) в какой моде будет применен данный шаблон, при том, что мода в нем не указана block('listitem').match(!this.inListItem)(apply({inListItem:true}))?.. 2) предположим, что все же я чего-то недопонял и все-таки шаблон из моего 1-го пункта все-таки выполнился. Все, что делает метод apply(исходя из документации) - "Конструкция apply предназначена для явного вызова процедуры выбора и выполнения шаблона, предикат которого истинен в данном контексте. Конструкция позволяет вызывать шаблоны в модифицированном контексте.". Иными словами метод apply в задаче-примере всего лишь изменит свойства текущего контекста(сугубо на время выполнения apply, после выполнения apply свойство inListItem вернется в свое начальное значение до вызова apply) и возвратит результат выполнения подходящего шаблона. Каким боком(при том, что inListItem после завершения вызова apply откатился к своему первоначальному значению) в задаче-примере пытаются заюзать inListItem в block('para').match(this.inListItem).tag()('')? 3) правильно ли я понимаю, что, если в теле шаблона я попытаюсь записать что-либо в нестандартное свойство контекста, например, вот так block('b1').content()(function(){this.HELLO = 'world'}), то после этого свойство HELLO будет доступно в контексте любого последующего обрабатываемого узла bem дерева? Либо при обработке каждого нового узла бэм дерева контекст(объект по ссылке this) пересоздается заного и, в связи с чем, поле HELLO будет отсутствовать для всех последующих обрабатываемых узлов bem дерева?
Заранее благодарю.
Например я могу использовать как this.ctx.block, так и this.block для получения имя блока.
Еще не понятная история с data, например если передать в bemhtml свойство data:
{
block: 'some-block',
data: 'some-data'
}
, то оно будет находится как и в this.ctx.data так и в this.data
Но если передать свойство отличное от data:
{
block: 'some-block',
anotherkey: 'some-data'
}
, то оно будет находится только в свойстве this.ctx.anotherkey
Следующие конструкции не работают:
block('block').elem('elem').elemMod('mod-name', 'mod-value')
block('block').elem('elem').mod('mod-name', 'mod-value')
Пример из руководства по технологии по bemhtml (http://ru.bem.info/technology/bemhtml/2.3.0/bemhtml-js-syntax/) вообще вызывает ошибку
block('b-head-logo')(elem('text').elemMod('size', 'big'))
Работает только следующая конструкция:
block('block').elem('elem').match('mod-value' == this.ctx.mods['mod-name'])
Я так понимаю это бага?
Проблема невероятно чудесная. Вот здесь https://github.com/verybigman/bem-grid/blob/8218ef38503fc224219788692e7ddcd965f6428e/common.blocks/row/row.deps.js
подключаю как зависимость по технологии bemhtml блоки i-bem
и row
. Ожидается, что шаблон row
попадет в бандл с browser.js. Но не все так просто. При запуске в браузере получаю ошибку: Uncaught Error: Module "row": can't resolve dependence "BEMHTML"
, тесты проходят безупречно. Почему в фантоме все ок, а в живом браузере нет? Народ, помогите, я спать не могу из-за этого. Сбросить кэш не предлагать. Подключать bemhtml.js тоже не true. Сборщик bem-tools.
Возможно ли создание в BEMHTML глобальной переменной доступной для всех шаблонов? т.е. например я хочу иметь объект к которому есть доступ из контекста любого шаблона.
Ввиду нетривиальных конфигов enb(Возможно только для меня), не понятно как использовать BH на клиенте. Хотелось бы посмотреть примеры использования. Интересно, какова судьба BEMHTML в связи с появлением BH.
Всем привет. Как заставить BEMHTML генерить не сжатый, а нормальный "бьютифицированный" код HTML? Спасибо.
Не могу разобраться с шаблонизацией на клиенте. Есть два блока content и list. Как сделать чтобы из блока content был виден шаблон list? Какие зависимости надо подключать и в каком порядке?
пробовал так:
modules.define('i-bem__dom', ['BEMHTML'], function(provide, BEMHTML, BEMDOM) {
BEMDOM.decl('content', {
onSetMod: {
'js':{
'inited': function(){
BEMDOM.append(
this.domElem,
BEMHTML.apply(
{
block: 'list'
})
);
}
}
}
});
provide(BEMDOM);
});
Дима Белицкий, в своем докладе в Москве выносит все миксы блоков в bemhtml блока, хотелось бы узнать насколько это правильно, выходит надо выносить миксы и модификаторы? Вообщем вопрос в том, когда стоит выносить сущности, а когда нет в bemhtml.
Да, и отсортируте плз теги по алфавиту
Правильно ли будет вынести content (текст) блока в bemhtml шаблон.
Блок используется в нескольких местах с одинаковым содержимым (текстом), ведь прописывать один и тот же текст в разных местах плохое решение
Есть БЭМ блок, у которого прописаны свои поведения. Изначально его на странице нет. но в deps он прописан поэтому все исходники подгружаются. Так вот. Надо чтобы по событию нажатия кнопки, в DOM добавлялся этот блок. Таких блоков может быть добавлено много. Необходимо чтобы он при всем при том еще и работал. Каким образом это сделать?
Есть какое-то стандартное решение?
Подскажите как создать блок BEM (в идеале из BEMJSON) в runtime, например по событию нажатия на кнопку, и добавить его в к содержимому другого блока.
Решил я попробовать обернуть сторонний виджет в блок БЭМ, возьмем например Yandex Share
<script type="text/javascript" src="//yandex.st/share/share.js"
charset="utf-8"></script>
<div class="yashare-auto-init" data-yashareL10n="ru"
data-yashareQuickServices="vkontakte,facebook" data-yashareTheme="counter"></div>
Я создаю блок bem create -l desktop.blocks -b yashare
с содержимым
# desktop.blocks/yashare/yashare.bemhtml
`block('yashare')(
tag()('div'),
bem()(false),
cls()('yashare-auto-init'),
attrs()({'data-yashareQuickServices': '...', 'data-yashareTheme': '...')
)
/* desktop.blocks/yashare/yashare.browser.js */
modules.define('yashare', ['loader_type_js'], function(provide, loader) {
loader('//yandex.st/share/share.js', provide);
});
А теперь вопрос, как воспользоваться данным блоком, чтоб подключения share.js было единожды (это уже реализует loader), но только в случае наличия на странице блоков yashare?
Если в yashare.browser.js добавить modules.require(['yashare'], function() {}); то подключение скрипта будет вне зависимости от наличия на странице блоков.
В качестве виджета может быть и другой, главная задумка, что скрипт подключается единожды независимо от количества блоков (виджетов) на одной странице.
P.S. Из-за плохой, не структурированной, а местами просто устаревшей документации - очень высокий порог вхождения...
Кажется, я упустила что-то из документации по bemhtml. Хочу ответы на следующие простые вопросы:
1) как в bemhtml связать input-radio с label, когда radio не находится внутри label?
2) как определить в bemhtml input-radio и label, когда radio внутри label?
в обоих случаях radio одиночный.
Примеры видела, пост про radio (http://ru.bem.info/libs/bem-components/v2/desktop/radio/docs/) читала.
block('content')
(
tag()('article'),
elemMatch()
(
tag()(this.ctx.elem)
)
);
Никак не пойму, почему не отрабатывает этот шаблон, а конкретно не подхватывает tag()('article')
, если убрать из шаблона elemMatch()
то тэг проставляется
Если есть у кого, прошу ссылочку. Хочется видеть сборку простого проекта с bemtree
Столкнулся с этой ошибкой когда решил положить блоки и бандлы в папку src/ на проекте и настроить сборку так.
/
.bem/
src/
desktop.blocks
desktop.bundles
в make.js
соответственно указал
getBundlesLevels: function() {
return [
'src/desktop.bundles'
];
}
Сборка происходит нормально, но в такой схеме сервер падает на этом then
BEMTREE.apply(json)
.then(function(bemjson) {
res.send(BEMHTML.apply(bemjson));
});
А если положить эти же папки, блоков и бандлов, в корень то все отрабатывает как надо.
Подскажике как поправить и настроить предложенную выше схему.
Весь кусок про сервер и шаблонизацию
var bemtreeTemplate = FS.readFileSync( './src/desktop.bundles/index/_index.bemtree.js'),
bemtmlTemplate = FS.readFileSync( './src/desktop.bundles/index/_index.bemhtml.js');
var context = VM.createContext({
Vow: vow,
console: console,
borschik: {
link: function(i) {
return i;
}
}
});
VM.runInContext(bemtreeTemplate, context);
BEMTREE = context.BEMTREE;
VM.runInContext(bemtmlTemplate, context);
BEMHTML = context.BEMHTML;
BEMTREE.apply(json)
.then(function(bemjson) {
res.send(BEMHTML.apply(bemjson));
});
До сих пор не могу понять магию 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);
}
)
);
Как сделать правильно?
Входящие: Есть редктор, который сохраняет примерно такие данные
post.html = '<p>\r\n\t\tСтремление к совершенству – пожалуй, именно так можно описать развитие человечества. Вот взять, к примеру, женскую красоту. Чего только не сделают девушки, чтобы оказаться самой красивой. ... .</p>\r\n\t<!-- gallery(3) --><p>\r\n\tА вот раньше оверклокинг существовал исключительно ради выгоды. ... </p><p><!-- gallery(4) --></p>'
В этой строке есть вставки коментариев. Задача: В контексте bemtree хочу заменить комнтарии на html код блока галлереи с слайдером. Хоче сделать примерно следующее:
post.galleries.map(function(gallery, index) {
var id = post.galleries_list[index].id,
images = post.galleries[index].images,
galleryBlock = {
block : 'slider',
slides : images
}; //Здесь что-то нужно сделать что бы распарсить блок в строку
post.html = post.html.replace('<!-- gallery(' + id +') -->', galleryBlock)
})
Вопрос: Как в bemtree/bemhtml распарсить блок в html строку? Или предложите другие варианты решения проблемы?