Варвара Степанова "БЭМ и JavaScript: Сборник рецептов"

Preview:

DESCRIPTION

Многие темы удобнее и интереснее изучать с помощью разных небольших примеров конкретных решений задач. Написание JavaScript для браузера с использованием i-bem.js – не исключение. Разберём задачи, основанные на реальной практике разных проектов Яндекса.

Citation preview

Я.Субботник, Москва, 8 сентября 2012 года

Варя Степановаруководитель группы разработки интерфейсов

БЭМ и JavaScript: Сборник рецептов

Вложенные блоки

4

Блоки b-menu-*

4

Блоки b-menu-*

5

Как работает b-menu-*?

this .trigger(‘current’);

6

b-seach

,nd*() методы

7

внутри

снаружи

на себе

BEM.DOM.decl('b-search', { onSetMod: { 'js': { 'inited': function() { this .findBlockInside( 'b-menu-vert') .on( 'current', this.doSmth() ); } } }}

8

...<div class="b-search__filter">

<div class="b-menu-vert i-bem" onclick="..."> ... </div>

</div>...

9

...

<div class="b-menu-vert i-bem b-search__filter" onclick="..."> ...</div>

...

10

this .findBlockInside( this.elem('filter'), 'b-menu-vert') .on('current', this.doSmth());

11

bit.ly/NfYdTa

12

Пример реиспользования меню

Декларативность

Декларативность в архитектуре

bit.ly/OptXT5

15

Презентация про Кнопочку на РИТ 2012

16

Состояния кнопки

16

Состояния кнопки

BEM.DOM.decl('b-form-button', { onSetMod : {

'focused' : {

'yes' : function() {

... this .bindTo('keydown', this._onKeyDown) .elem('input').focus();

17

18

b-map & i-geo-point

{ block: 'b-map',

mods: { ... },

js: { ... center: [ 37.58, 55.73 ], zoom: 16, points: [ ... ] }

}

19

bit.ly/RdKGNA

20

Пример Яндекс.Карты на БЭМ

Переопределение уровнем

Переопределение в CSS

22

library/blocks/b-head/b-head.css-----------------------------------------

.b-head { color: red; }

Переопределение в CSS

22

library/blocks/b-head/b-head.css-----------------------------------------

.b-head { color: red; }

blocks/b-head/b-head.css-----------------------------------------

.b-head { color: green; }

Переопределение в CSS

22

Переопределение динамического метода

b-9ash

24

b-9ash

24

getDefaultParams : function() {

return {

version : '10.0.0', width : '100%', height : '100%', attributes : {}, ... };

}

25

getDefaultParams : function() {

return {

version : '10.0.0', width : '50%', height : '50%', attributes : {}, ... };

}

26

getDefaultParams : function() {

return $.extend( this.__base(), { width: '50%', height: '50%' } );

}

27

Переопределение статического свойства

b-serp

29

b-serp

29

BEM.DOM.decl('b-serp', { // динамические поля}, { blocks: []});

blocks-common/b-serp/b-serp.js

30

blocks/b-serp/b-serp.jsBEM.DOM.decl('b-serp', {}, { blocks: [ 'b-form-input', 'b-adv', 'b-serp-list', 'b-more', 'b-feet' ]});

blocks-new/b-serp/b-serp.jsBEM.DOM.decl('b-serp', {}, { blocks: [ 'b-form-input', 'b-adv', 'b-filters', 'b-serp2-list', 'b-more', 'b-feet' ]});

31

Переопределение модификатором

b-form-input

33

b-form-inputb-form-input_autocomplete_yes

34

BEM.DOM.decl('b-form-input', { onSetMod : { 'js' : { 'inited' : function() { // инициализация } }, 'focused' : { 'yes' : { // что делать, когда в фокусе } } }}

35

36

BEM.DOM.decl({ block: 'b-form-input', modName: 'autocomplete', modVal: 'yes' },

36

BEM.DOM.decl({ block: 'b-form-input', modName: 'autocomplete', modVal: 'yes' }, { onSetMod: { 'js': { 'inited': function() { this.__base.apply(this, arguments); // расширение // функциональности }, ...

36

BEM.DOM.decl({ block: 'b-form-input', modName: 'autocomplete', modVal: 'yes' }, { onSetMod: { ...

37

BEM.DOM.decl({ block: 'b-form-input', modName: 'autocomplete', modVal: 'yes' }, { onSetMod: { ... 'focused': { 'yes': function() { this.__base(); // расширение //функциональности }, '': function() { ... }

37

live-события

39

39

BEM.DOM.decl('b-form-select', {...}, {

live: function() {

this.liveBindTo( 'item', 'mouseup', function() { ... }

}

});

40

live-инициализация

42

42

43

43

43

BEM.DOM.decl('b-block', { ... },

{ /* Статические методы и свойства */

}

);

44

BEM.DOM.decl('b-block', { ... },

{ live: function() { /* Когда инициализировать? */

}

}

45

live: function() {

this.liveInitOnEvent(...)

.liveInitOnBlockEvent(...)

.liveInitOnBlockInsideInit(...)

.liveInitOnBlockInsideEvent(...)

.liveInitOnBlockInit(...)

}

46

this

.liveBindTo('leftclick', function(e){ this._onClick(e); })

.liveBindTo( 'mouseover ... focusin', function(e) { var mod = eventsToMods[e.type]; this.setMod(mod.name, mod.val || ''); }); }

47

Миксование блоков

<div class="b-block1 b-block2 i-bem" onclick=" return { 'b-block1': {}, 'b-block2': {} } ">

Миксование блоков

49

<div class="b-domik b-c i-bem" onclick="return { 'b-domik' : {...}, 'b-c' : { .. } }"> ... <a class="b-domik__help"> Помощь </a> ...</div>

Блок сбора статистики кликов

50

baseBlock

52

Блоки b-menu-*

52

Блоки b-menu-*

BEM.DOM.decl('i-menu', {

onElemSetMod : {

'item' : { 'state' : { 'current' : function(...) { ... this.trigger('current'); } }

} }});

53

blocks-desktop/b-menu-horiz/b-menu-horiz.jsBEM.DOM.decl( { name: 'b-menu-horiz', baseBlock: 'i-menu' });

blocks-desktop/b-menu-vert/b-menu-vert.jsBEM.DOM.decl( { name: 'b-menu-vert', baseBlock: 'i-menu' });

54

55

bit.ly/Tq5aU4Блок i-menu

Распределённый :-) блок

Один и тот же блок

57

<div class="b-my-block i-bem" onclick="return { 'b-my-block' : { 'id' : 'myBlockId' } }"> <!-- smth --> </div>

<div class="b-my-block i-bem" onclick="return { 'b-my-block' : { 'id' : 'myBlockId' } }”> <!-- smth else --> </div>

58

b-tabbed-pane

59

<div class="b-tabbed-pane b-tabbed-pane__tabs i-bem" onclick="return {'b-tabbed-pane':{'id':'myTabbedPaneId'}}">

<div class="b-tabbed-pane b-tabbed-pane__panels i-bem" onclick="return {'b-tabbed-pane':{'id':'myTabbedPaneId'}}">

60

Блок без DOM-представления

BEM.decl('i-system', {

// динамические поля

}, {

// статические поля

});

62

BEM.decl('i-system', {

// динамические поля

}, {

// статические поля

});

BEM.DOM.decl(...)

62

channel

BEM.channel('channelName');

BEM .channel('channelName') .trigger('event');

BEM.channel('channelName').on();

BEM.channel('channelName').un();

channel API

64

var channel = BEM.channel('sys');

BEM.decl('i-system', {}, {

// каждые 50 милисекунд channel.trigger('tick');

// если активности нет channel.trigger('idle');

// при mousemove и keydown channel.trigger('wakeup');

});

65

BEM.DOM.decl('b-form-input', { 'js' : { 'inited' : function() { ... var sys = this.channel('sys').on({ 'tick' : update, 'idle' : function() { сhannel.un('tick', update); }, 'wakeup' : function() { сhannel.on('tick', update); } }); } },

66

67

update = function () { var inst, i = 0; while(inst = inst[i++]) inst.val(in.elem('input').val());}

67

update = function () { var inst, i = 0; while(inst = inst[i++]) inst.val(in.elem('input').val());}

BEM.DOM.decl('b-form-input', { ...

67

update = function () { var inst, i = 0; while(inst = inst[i++]) inst.val(in.elem('input').val());}

BEM.DOM.decl('b-form-input', { ... val : function(val, data) { if (val != oldVal) this.trigger('change', data); } ...});

67

bit.ly/OVJHhsБлок i-system, c примером

68

69