EN
godfreyd
godfreyd
7 сентября 2017

Привет!

Наверняка все знают про шаблонный репозиторий для динамических проектов bem-express.

Если вы еще до конца не разобрались, как внутри него все устроено, то для вас мы написали tutorial: «Переходим на сторону сервера с bem-express».

API bem-express

c1n1k
c1n1k
20 сентября 2017

Как устроена серверная сторона БЭМа, как с рендерингом на сервере, с ruby, какие трудности при развертывании? Я вот сейчас общаюсь и мне приводят аргумент, что это еще и лишний гемор на сервере с js и нагрузку на сервер увеличивает, что приводит к удоражанию.

Можете показать сайты которые полностью на стеке БЭМа. НЕ ЯНДЕКС, а то при слове БЭМ у всех Яндекс, много датацентров, много бабок на сервера и тп.

legostaev-vadim
legostaev-vadim
18 сентября 2017

gulp-pugbem

NPM
GitHub

Установка

npm install gulp-pugbem --save-dev

Подключение

var gulp = require('gulp');
var pug = require('gulp-pug');
var pugbem = require('gulp-pugbem');

gulp.task('pages', function () {
    return gulp.src('app/**/*.pug')
        .pipe(pug({
            plugins: [pugbem]
        }))
        .pipe(gulp.dest('dist'));
});

Использование

Блок

блок в pug-коде начинается с точки [перед которой может стоять название тега]
блоки можно вкладывать друг в друга, как показано во втором примере

.header
form.search-form

.header
    nav.menu

result:

<div class="header"></div>
<form class="search-form"></form>

<div class="header">
    <nav class="menu"></nav>

Элемент

элемент в pug-коде начинается с точки и знака подчеркивания [перед которыми может стоять название тега]
в примере ниже, блок search-form включает два элемента input и button

form.search-form
    input._input
    button._button Search

result:

<form class="search-form">
    <input class="search-form__input">
    <button class="search-form__button">Search</button>
</form>

Модификатор

модификатор в pug-коде начинается с точки и дефиса [перед которыми должен идти блок или элемент]
в примере ниже, модификатор назначен блоку search-form и элементу button

Булевый

form.search-form.-focused
    button._button.-disabled Search

result:

<form class="search-form search-form--focused">
    <button class="search-form__button search-form__button--disabled">Search</button>
</form>

Ключ-значение

form.search-form.-theme_islands
    button._button.-size_m Search

result:

<form class="search-form search-form--theme_islands">
    <button class="search-form__button search-form__button--size_m">Search</button>
</form>

Микс

микс в pug-коде состоит из блока и следующего за ним одноименного элемента без названия тега [перед элементом не может идти ничего, кроме одноименного блока]

миксы не могут использоваться сами по себе, они являются строительной частью другого блока
в примере ниже, блок header включает микс search-form

.header
    form.search-form._search-form

result:

<div class="header">
    <form class="search-form header__search-form"></form>
</div>

Пример

header.header
    nav.menu
        a(href="#")._logo Company
        .list
            a._item.-active(href="#") Home
            a._item(href="#") News
            a._item(href="#") Gallery
            a._item(href="#") Partners
            a._item(href="#") About
            a._item(href="#") Contacts
    h1._title Hello, World!
    .myslider._myslider
        ._slide Content
        ._slide.-active Content
        ._slide Content
    p._text Good weather

result:

<header class="header">
    <nav class="menu">
        <a class="menu__logo" href="#">Company</a>
        <div class="list">
            <a class="list__item list__item--active" href="#">Home</a>
            <a class="list__item" href="#">News</a>
            <a class="list__item" href="#">Gallery</a>
            <a class="list__item" href="#">Partners</a>
            <a class="list__item" href="#">About</a>
            <a class="list__item" href="#">Contacts</a>
        </div>
    </nav>
    <h1 class="header__title">Hello, World!</h1>
    <div class="myslider header__myslider">
        <div class="myslider__slide">Content</div>
        <div class="myslider__slide myslider__slide--active">Content</div>
        <div class="myslider__slide">Content</div>
    </div>
    <p class="header__text">Good weather</p>
</header>

Параметры

var pugbem = require('gulp-pugbem');

// разделитель элементов
pugbem.e = 'string';

// разделитель модификаторов
pugbem.m = 'string';

Пример

pugbem.e = '**';
form.search-form
    input._input

result:

<form class="search-form">
    <input class="search-form**input">
</form>

pugbem.m = '++';
form.search-form.-focused

result:

<form class="search-form search-form++focused"></form>

Это может пригодиться, например, когда для разделения модификаторов предпочтение отдается классическому определению.

Имя модификатора отделяется от имени блока или элемента одним подчеркиванием (_)

Тогда необходимо задать свойству m соответствующее значение:

pugbem.m = '_';
form.search-form.-focused

result:

<form class="search-form search-form_focused"></form>

License

MIT License

Copyright (c) 2017 Legostaev Vadim (legostaev.vadim@mail.ru)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

joshuan
joshuan
16 сентября 2017

Добрый день.
Есть такой пробный проект: https://github.com/joshuan/integrate-webpack-bem-loader
Сборка его собирается нормально:

$ webpack
Hash: 3819d0b165d22e9cf6d0
Version: webpack 2.7
Time: 1075ms
    Asset    Size  Chunks             Chunk Names
bundle.js  158 kB       0  [emitted]  main
   [0] ./~/process/browser.js 5.42 kB {0} [built]
   [5] ./~/object-assign/index.js 2.11 kB {0} [built]
   [7] ./~/react/lib/canDefineProperty.js 661 bytes {0} [built]
   [8] ./blocks/logo/logo.js 2.3 kB {0} [built]
  [11] ./~/react/lib/lowPriorityWarning.js 2.16 kB {0} [built]
  [14] ./~/react/lib/ReactBaseClasses.js 5.44 kB {0} [built]
  [25] ./~/react/lib/React.js 5.08 kB {0} [built]
  [26] ./~/react/lib/ReactChildren.js 6.19 kB {0} [built]
  [27] ./~/react/lib/ReactDOMFactories.js 5.48 kB {0} [built]
  [29] ./~/react/lib/ReactPropTypes.js 500 bytes {0} [built]
  [31] ./~/react/lib/ReactVersion.js 350 bytes {0} [built]
  [33] ./~/react/lib/createClass.js 688 bytes {0} [built]
  [34] ./~/react/lib/onlyChild.js 1.34 kB {0} [built]
  [36] ./~/react/react.js 56 bytes {0} [built]
  [37] ./src/index.js 307 bytes {0} [built]
    + 23 hidden modules

Но стоит лишь добавить redux: https://github.com/joshuan/integrate-webpack-bem-loader/pull/1
то сборка рушится.
Один в один в другую сторону - при живом redux, подключая webpack-bem-loader: https://github.com/joshuan/integrate-webpack-bem-loader/pull/2

$ webpack
Hash: f8c94748da0b23692e0f
Version: webpack 2.7.0
Time: 1455ms
    Asset    Size  Chunks             Chunk Names
bundle.js  159 kB       0  [emitted]  main
   [3] ./~/react/lib/ReactElement.js 11.2 kB {0} [built]
   [5] ./~/object-assign/index.js 2.11 kB {0} [built]
   [7] ./~/react/lib/canDefineProperty.js 661 bytes {0} [built]
   [8] ./blocks/logo/logo.js 2.32 kB {0} [built]
  [11] ./~/react/lib/lowPriorityWarning.js 2.16 kB {0} [built]
  [14] ./~/react/lib/ReactBaseClasses.js 5.44 kB {0} [built]
  [25] ./~/react/lib/React.js 5.08 kB {0} [built]
  [27] ./~/react/lib/ReactDOMFactories.js 5.48 kB {0} [built]
  [29] ./~/react/lib/ReactPropTypes.js 500 bytes {0} [built]
  [31] ./~/react/lib/ReactVersion.js 350 bytes {0} [built]
  [33] ./~/react/lib/createClass.js 688 bytes {0} [built]
  [34] ./~/react/lib/onlyChild.js 1.34 kB {0} [built]
  [36] ./~/react/react.js 56 bytes {0} [built]
  [37] ./~/redux/es/index.js 878 bytes {0} [built] [failed] [1 error]
  [38] ./src/index.js 307 bytes {0} [built]
    + 24 hidden modules

ERROR in ./~/redux/es/index.js
Module build failed: SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' (1:0)
    at Parser.pp$4.raise (/Users/joshuan/www/_test/babel-webpack/node_modules/acorn/dist/acorn.js:2610:13)
    at Parser.pp$1.parseStatement (/Users/joshuan/www/_test/babel-webpack/node_modules/acorn/dist/acorn.js:782:16)
    at Parser.pp$1.parseTopLevel (/Users/joshuan/www/_test/babel-webpack/node_modules/acorn/dist/acorn.js:690:23)
    at Parser.parse (/Users/joshuan/www/_test/babel-webpack/node_modules/acorn/dist/acorn.js:543:15)
    at parse (/Users/joshuan/www/_test/babel-webpack/node_modules/acorn/dist/acorn.js:3669:37)
    at module.exports (/Users/joshuan/www/_test/babel-webpack/node_modules/falafel/index.js:22:15)
    at Object.module.exports (/Users/joshuan/www/_test/babel-webpack/node_modules/webpack-bem-loader/index.js:43:20)
 @ ./blocks/logo/logo.js 13:0-16
 @ ./src/index.js
kompolom
kompolom
13 сентября 2017

Ситуация такая: использую borschik-js-include для подтянивания файлов из node_modules. Бандлы собираются - тесты (specs) не собираются.
Пробовал решить ситуацию кардинально и заиспользовал browserify но столкнулся с той же самой проблемой.

asakasinsky
asakasinsky
13 октября 2014

Доброго времени суток.
Где можно посмотреть UI Elements Naming Convention (соглашение как называть тот или иной контрол графического интерфейса), используемый в Яндексе?

bonjovi
bonjovi
12 сентября 2017

Добрый вечер

Пытаюсь вывести данные из JSON, как сказано здесь - https://ru.bem.info/forum/716/

Ничего не выходит, помогите найти ошибку

Вывожу вот так - http://joxi.ru/V2VL9x3SxLX34r

Выдаёт ошибку TypeError: Cannot read property 'apply' of undefined
http://joxi.ru/1A5xBqGsnO6Nd2

В переменную BEMTREE почему-то ничего не приходит.

Проверил в вышеобозначенном файле page.bemtree.js через console.log() значения этих четырёх переменных:

  • PATH
  • pathToBundle
  • BEMTREE
  • BEMHTML

Все имеют значение, кроме BEMTREE имеющей undefined

Сборку свою текущую загрузил сюда - https://yadi.sk/d/6WCDVmYN3MqEBL

lilliputten
lilliputten
12 сентября 2017

Не могу разобраться по описанию в разделе Декларация блока, как примешивать блок (отдельный специально подготовленный миксин?) к элементу или модификатору. Ткните меня, пож., в примеры использования declMixin? В bem-core, bem-components что-то не вижу ничего.

bonjovi
bonjovi
6 сентября 2017

Добрый день

По умолчанию project stub стили для /desktop.bundles/index/index.bemjson.js ищет в папках /common.blocks и /desktop.blocks

Как сделать так, чтобы он искал например только в /desktop.blocks/index

Мне нужно чтобы стили для /desktop.bundles/index/index.bemjson.js искались в /desktop.blocks/index
А для /desktop.bundles/index2/index2.bemjson.js искались в в /desktop.blocks/index2

sinitsyn-alex
sinitsyn-alex
1 сентября 2017

Появилась необходимость принудительно сбрасывать кэш css, js бандлов на страницах.
Смотрел в сторону добавления версий по типу: index.css?v=2 или index.css?v= new Date()
Как лучше всего реализовать "версионность" бандлов для project-stub?
В make.js? Или есть готовый инструмент-модуль для бэм-а в целом?
Было бы не плохо увидеть пример этой реализации.

lilliputten
lilliputten
4 сентября 2017

Есть примерно следующая структура вложенных блоков:

{
    block : 'box',
    mods : {
        root : true,
        id : 'layoutBox',
    },
    content : {
        block : 'box',
        mods : {
            id : 'appBox',
        },
        // Имеем некоторую вложенность блоков `box`: layoutBox->appBox->ReportLayout->Report->ReportDisplay; Т.е.:
        // ...
        content : {
            block : 'ReportDisplay',
            mix : {
                block : 'box',
                mods : {
                    id : 'ReportDisplay',
                },
            },
            content : {
                // Some content...
            },
        },
    },
}

При удалении блока ReportDisplay (при помощи BEMDOM.destruct(ReportDisplay.domElem)) по цепочке parentNode (в jquery) до верхнего уровня (layoutBox) всплывает событие на delMod('js'), в результате чего блок отписывается от событий, зарегистрированных на window (ранее подписываемся так: this._domEvents(BEMDOM.win).on('resize',...)).

Стек выглядит примерно так:

    (i-bem-dom__events.js:155) this._storage[e] = null; // e='resize' -- Это собственно удаление подписанного события в _unbindByEvent.
    // ...
    (i-bem-dom__events.js:139) objects.each(this._storage, this._unbindByEvent, this); // this._storage={resize:{uniq161:{...}}}
    (i-bem-dom__events.js:253) params.bindToArbitraryDomElem && ctxStorage[storageKey] &&
                            ctxStorage[storageKey].un();
    (i-bem-dom__events_type_bem.js:85) fn.call(fnCtx || instance, originalEvent, data); // fnCtx=null, instance=layoutBox, originalEvent={bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}, data={modName:'js', modVal:'',oldModVal:'inited'}
    (jquery:5205) ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||     //  handleObj.origType='__bem__box_js_'
                        handleObj.handler ).apply( matched.elem, args ); //  matched.elem=layoutBox.domElem[0], args=[jQuery.Event{type:'__bem__box_js_'},{modName:'js', modVal:'',oldModVal:'inited'},{fns:{uniq151:true},propagationStoppedDomNode:null},{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}]
    (jquery.js:5014) jQuery.event.dispatch.apply( elem, arguments ); // elem=layoutBox.domElem[0], ...
    (jquery:8201) handle.apply( cur, data ); // cur=layoutBox.domElem[0], data=[jQuery.Event{type:'__bem__box_js_'},{modName:'js', modVal:'',oldModVal:'inited'},{fns:{uniq151:true},propagationStoppedDomNode:null},{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}]
    (jquery.js:8262) jQuery.event.trigger(type, data, this); // type='__bem__box_js_', data=[{modName:'js', modVal:'',oldModVal:'inited'},{fns:{uniq151:true},propagationStoppedDomNode:null},{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}], this=ctx
    (jquery.js:8269) ctx.domElem.trigger(event, [data, { fns : {}, propagationStoppedDomNode : null }, originalEvent]); // event='__bem__box_js_', data={modName:'js',modVal:'',oldModVal:'inited'}, originalEvent:{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}
    // ...
    (i-bem-dom.js:676) bemEvents.emit(this, e, data); // e={modName:'js',modVal:''}, data={modName:'js', modVal:'',oldModVal:'inited'}
    (i-bem-dom.js:733) this._emit({ modName : 'js', modVal : '' }, eventData); // eventData={modName:'js',modVal:'',oldModVal:'inited'}
    (i-bem.vanilla.js:324) this._afterSetMod('js', '', 'inited');
    (i-bem.vanilla.js:382) this.setMod('js', '');
    (i-bem.vanilla.js:247) this.delMod('js');
    (i-bem-dom.js:244) entity._delInitedMod();
    (i-bem-dom.js:1004) removeDomNodeFromEntity(entity, domNode);
    // ...
    (i-bem-dom.js:1029) this._destruct(ctx, excludeSelf, true);
    BEMDOM.destruct(ReportDisplay.domElem);

Полностью слепок вершины стека из DevTools, от destruct до _unbindByEvent).

_unbindByEvent (i-bem-dom__events.js:155)
each (objects.vanilla.js:56)
un (i-bem-dom__events.js:139)
(anonymous) (i-bem-dom__events.js:254)
inherit._createEventManager (i-bem-dom__events_type_bem.js:85)
dispatch (jquery.js:5206)
jQuery.event.add.elemData.handle (jquery.js:5014)
trigger (jquery.js:8201)
(anonymous) (jquery.js:8269)
each (jquery.js:362)
each (jquery.js:157)
trigger (jquery.js:8268)
emit (i-bem-dom__events_type_bem.js:119)
_emit (i-bem-dom.js:676)
_afterSetMod (i-bem-dom.js:733)
setMod (i-bem.vanilla.js:324)
delMod (i-bem.vanilla.js:382)
_delInitedMod (i-bem.vanilla.js:247)
removeDomNodeFromEntity (i-bem-dom.js:244)
(anonymous) (i-bem-dom.js:1004)
each (objects.vanilla.js:56)
(anonymous) (i-bem-dom.js:1000)
each (jquery.js:362)
each (jquery.js:157)
_destruct (i-bem-dom.js:993)
destruct (i-bem-dom.js:1029)

Т.е., раскрутить до конца я раскрутил, но вот дальше собственных мозгов разбраться, почему так происходит, как-то уже не хватает, увы. %((

Пока обхожусь принудительной переинициализацией событий на верхнем уровне после изменения содержимого.

Хелп? Что это может быть?

Версии библиотек:

  • bem-core@4.2.1
  • jquery@3.2.1
gwer
gwer
5 сентября 2017

Что-то я сломался на этом месте.

Вот есть у меня, скажем, блок input из bem-components. К нему примиксован элемент моего блока. Скажем, my-block__control.

{
    block: 'input',
    mix: { block: 'my-block', elem: 'control }
}

Из my-block легко получить этот input:
const input = this.findChildElem('control').findMixedBlock(Input).

Но можно ли аналогичным образом теперь из input получить элемент control? Например, input'ов много, я вешаю обработчик onchange на них, и этот обработчик должен взаимодействовать с миксованным элементом control. Каким-то из методов поиска можно к нему обратиться? Хочется что-то вроде такого:
input.findMixed*({ block: 'my-block', elem: 'control' })

Или только заранее формировать соответствия блоков и элементов и по ним уже ориентироваться?

sermonis
sermonis
4 сентября 2017

Добрый день!

Заметил следующее поведение bem-components на TOUCH-PAD и TOUCH-PHONE-устройствах: блоки (select, button, radio-group и т.д) срабатывают только при повторном нажатии (tap). После первичной инициализации конкретного блока проблема исчезает, срабатывает сразу. Подобное поведение наблюдалось на планшете iPad и двух Android-телефонах. Заметил сначала в проекте, потом проверил тут: bem-components / 6.0.0, описанное поведение воспроизвелось.

Подскажите, пожалуйста как побороть. Не хотелось бы отказываться от ленивой инициализации.

sinitsyn-alex
sinitsyn-alex
27 августа 2017

Всем доброго времени суток.
Появилась необходимость доопределить js для блока Attach.
А именно, при выборе картинки рисовать preview аватара.
Код:

/* desktop.blocks/attach/attach.js */
modules.define('attach', function(provide, Attach) {
    provide(Attach.decl({ modName: 'type', modVal: 'avatar' }, {
        onSetMod: {
            'js': {
                'inited': function() {
                    this.__base.apply(this, arguments);
                    console.log('attach_type_avatar inited...');
                }
            }
        },
        _updateFileElem: function() {
            this.__base.apply(this, arguments);
            console.log('_updateFileElem');
            //Do something...
        },
        _clear: function() {
            this.__base.apply(this, arguments);
            console.log('_clear');
            //Do something...
        }
    }));
});

Методы срабатывают,
"Супер-колл" работает,
Функциональность блока не ломается,
только после выбора файла, всплывает ошибка:

Uncaught TypeError: Cannot read property '_emitChange' of undefined
at Object._onChange (profile_settings.min.js:7695)
at n.fn.init.<anonymous> (profile_settings.min.js:1643)
at Function._liveClassTrigger (profile_settings.min.js:1618)
at HTMLBodyElement.f (jquery.min.js:2)
at HTMLBodyElement.dispatch (jquery.min.js:3)
at HTMLBodyElement.r.handle (jquery.min.js:3)

Конкретно в этом месте:

_onChange : function() {
        this.elem('no-file').detach();
        this.getVal()?
            this
                ._updateFileElem()
                ._emitChange() :
            this._clear();
}

Как побороть ошибку? Доопределяю кнопки таким же образом - нет никаких ошибок.

По данному запросу найдены посты в архиве:
Перейти в архив

Сортировка

Метки