Post on 15-Jun-2015
description
руководитель отделаразработки поисковых интерфейсов
Клиентский JavaScriptв БЭМ-терминахСергей Бережной
Вступление
Кто я?
Вступление
Кто я?
• Разработчик интерфейсов Яндекса с 2005 года• Руководитель отдела разработки поисковых интерфейсов• БЭМ-соавтор
4
@veged
github.com/veged
Кто вы?
Вступление
Основная часть
Низкий уровень
Основная часть
jQuery
8
jQuery
• Кроссбраузерность
9
jQuery
• Кроссбраузерность– события
10
jQuery
• Кроссбраузерность– события– селекторы
11
jQuery
• Кроссбраузерность– события– селекторы– манипуляция с DOM, CSS
12
jQuery
• Кроссбраузерность– события– селекторы– манипуляция с DOM, CSS– AJAX
13
jQuery
• Кроссбраузерность• Сахар
14
jQuery
• Кроссбраузерность• Сахар
– $.each
15
jQuery
• Кроссбраузерность• Сахар
– $.each– $.map
16
jQuery
• Кроссбраузерность• Сахар
– $.each– $.map– $.extend
17
jQuery
• Кроссбраузерность• Сахар
– $.each– $.map– $.extend– $.isArray, $.isFunction, $.isNumeric, ...
18
jQuery
• Кроссбраузерность• Сахар
– $.each– $.map– $.extend– $.isArray, $.isFunction, $.isNumeric, ...– ...
19
jQuery
• Кроссбраузерность• Сахар• Неймспейс для модулей
20
jQuery
• Кроссбраузерность• Сахар• Неймспейс для модулей
– $.debounce, $.throttle– $.observable– $.identify– $.inherit
21
INHERIT
22
github.com/dfilatov/node-inherit
INHERIT
23
inherit( // родительский класс, { // методы и поля экземпляра }, { // методы и поля класса (статические) })
INHERIT
24
inherit( parent, { myMethod: function() { this // экземпляр this.__self // класс this.__self.myStaticMethod() // вызов стат. метода this.__base() // super call } }, { // методы и поля класса (статические) })
INHERIT
25
inherit( parent, { // методы и поля экземпляра }, { myStaticMethod: function() { this // класс this.__base() // super call } })
INHERIT
26
BEM.decl( // что декларируем, { // методы и поля экземпляра }, { // методы и поля класса (статические) })
БЭМ
27
BEM.decl( 'my-block', { // методы и поля экземпляра }, { // методы и поля класса (статические) })
БЭМ
28
BEM.decl( { block: 'my-block', modName: 'm', modVal: 'v' }, { // методы и поля экземпляра }, { // методы и поля класса (статические) })
БЭМ
29
BEM.decl( { block: 'my-block', modName: 'm', modVal: 'v' }, { myMethod: function() { this.__base() // предыдущая декларация блока } }, { myStaticMethod: function() { this.__base() // предыдущая декларация блока } })
БЭМ
30
BEM.DOM.decl( // что декларируем, { // методы и поля экземпляра }, { // методы и поля класса (статические) })
БЭМ
31
Инициализация
Основная часть
Инициализация
33
Инициализация
33
Инициализация
34
Инициализация
• HTML «оживляется» с помощью JS
34
Инициализация
• HTML «оживляется» с помощью JS• DOM строится из JS
34
Инициализация
35
Инициализация
• HTML «оживляется» с помощью JS
35
Инициализация
• HTML «оживляется» с помощью JS– прогрессивный рендеринг
35
Инициализация
• HTML «оживляется» с помощью JS– прогрессивный рендеринг– unobtrusive
35
Инициализация
• HTML «оживляется» с помощью JS– прогрессивный рендеринг– unobtrusive– агенты без JS
35
Инициализация
• HTML «оживляется» с помощью JS– прогрессивный рендеринг– unobtrusive– агенты без JS
• DOM строится из JS
35
Инициализация
• HTML «оживляется» с помощью JS– прогрессивный рендеринг– unobtrusive– агенты без JS
• DOM строится из JS– простая связь HTML и JS
35
Инициализация
36
Инициализация
• императивно
36
Инициализация
• императивно• декларативно
36
Инициализация: императивно
37
$.fn.myPlugin = function() { this.fadeIn( 'normal', function() { ... });};
$('#element').myPlugin();
Инициализация: императивно
38
Инициализация: декларативно
39
<div class="my-plugin"> ...</div>
Инициализация: декларативно
40
$.fn.myPlugin = function() { // ...};
$(function() { $('.my-plugin').myPlugin();});
Инициализация: декларативно
41
$(function() { $('.my-plugin').myPlugin();});
$(function() { $('.other-plugin').otherPlugin();});
Инициализация: декларативно
42
<div class="my-plugin i-bem"> ...</div>
Инициализация: декларативно
43
$(function() { $('.i-bem').each(function() { // init })})
Инициализация: декларативно
44
Параметры
45
Параметры
46
<input class="my-input" data-validator="login" name="login" value=""/>
Параметры
47
this.data('validator') === 'login'
Параметры
48
<input class="my-input" onclick="return { validator: 'login' }" name="login" value=""/>
Параметры
49
this[0].onclick().validator === 'login'
Параметры
50
<input class="my-input" onclick="return { validator: { ... } }" name="login" value=""/>
Параметры
51
<input class="my-input" onclick="return { validator: function() { ... } }" name="login" value=""/>
Параметры
52
<input class="my-input" onclick="return { validator: require('validators').login }" name="login" value=""/>
Параметры
53
Инициализация + параметры
54
<div class="my-plugin i-bem" onclick="{ 'my-plugin': { 'my-param': 1 } }" > ...</div>
Инициализация + параметры
55
<div class="my-plugin other-plugin i-bem" onclick="{ 'my-plugin': {} 'other-plugin': {} }" > ...</div>
Инициализация + параметры
56
AJAX
57
AJAX
58
AJAX
• динамическая инициализация
58
AJAX
• динамическая инициализация• destruct
58
$.ajax({ url: '...', success: function(data) { $('body').append(data) }})
Динамическая инициализация
59
$.fn.myPlugin = function() { this.fadeIn( 'normal', function() { ... });};
$('#element').myPlugin();
Динамическая инициализация
60
$.ajax({ url: '...', success: function(data) { BEM.DOM.append('body', data) }})
Динамическая инициализация
61
$.ajax({ url: '...', success: function(data) { BEM.DOM.update('body', data) }})
Destruct
62
Ленивая инициализация
63
$.fn.myPlugin = function() { ... };
$(function() { $('body').on('click', '.myPlugin', function() { $(this).myPlugin() })});
Ленивая инициализация
64
BEM.DOM.decl('my-block', { /* методы и поля экземпляра */ }, { live: function() { // исполнится один раз } })
Ленивая инициализация
65
BEM.DOM.decl('my-block', { /* методы и поля экземпляра */ }, { live: function() { this.liveBindTo( 'item', 'mouseup', function() { ... } } })
Ленивая инициализация
66
BEM.DOM.decl('my-block', { /* методы и поля экземпляра */ }, { live: function() { this.liveInitOnEvent(...) .liveInitOnBlockEvent(...) .liveInitOnBlockInsideInit(...) .liveInitOnBlockInsideEvent(...) .liveInitOnBlockInit(...) } })
Ленивая инициализация
67
bit.ly/i-bem-liveinit
Ленивая инициализация
68
Состояния инициализации
69
<div class="my-plugin my-plugin_js_init i-bem" onclick="{ 'my-plugin': {} }" > ...</div>
Состояния инициализации
70
<html class="i-ua_js_yes i-ua_css_standard">
Состояния инициализации
71
.i-ua_js_no .my-plugin { display: none;}
Состояния инициализации
72
.i-ua_js_no .my-plugin { display: none;}
.i-ua_js_yes .my-plugin { visibility: hidden;}
Состояния инициализации
73
.i-ua_js_no .my-plugin { display: none;}
.i-ua_js_yes .my-plugin { visibility: hidden;}
.i-ua_js_yes .my-plugin_js_init { visibility: visible;}
Состояния инициализации
74
БЭМ
Основная часть
БЭМ
76
БЭМ
• селекторы
76
БЭМ
• селекторы– блоки
76
БЭМ
• селекторы– блоки– элементы (в том числе кеширование)
76
БЭМ
• селекторы– блоки– элементы (в том числе кеширование)
• модификаторы
76
БЭМ
• селекторы– блоки– элементы (в том числе кеширование)
• модификаторы– установка, проверка
76
БЭМ
• селекторы– блоки– элементы (в том числе кеширование)
• модификаторы– установка, проверка– декларация для модификаторов
76
Файлы
Основная часть
bem-bl/blocks-desktop/
Файлы
78
bem-bl/ blocks-common/blocks-desktop/
Файлы
79
bem-bl/ blocks-common/ i-bem/blocks-desktop/ my-block/
Файлы
80
bem-bl/ blocks-common/ i-bem/ __dom/ i-bem__dom.js ... i-bem.js ...blocks-desktop/ my-block/ my-block.css my-block.js
Файлы
81
blocks-desktop/my-block/my-block.js
BEM.DOM.decl( 'my-block', { /* методы и поля экземпляра */ }, { /* статические методы и поля */ })
Файлы
82
bem-bl/blocks-desktop/pages/ index/ index.bemdecl.js // декларация index.js // сборка
Файлы
83
pages/index/index.js/* borschik:include:../../bem-bl/blocks-common/i-bem/__dom/i-bem.js *//* borschik:include:../../bem-bl/blocks-common/i-bem/__dom/i-bem__dom.js *//* borschik:include:../../blocks-desktop/my-block/my-block.js */
Файлы
84
Зависимости
85
bem-bl/ blocks-common/ i-bem/ __dom/ i-bem__dom.js i-bem__dom.deps.js i-bem.js i-bem.deps.jsblocks-desktop/ my-block/ my-block.js my-block.deps.js
Зависимости
86
blocks-desktop/my-block/my-block.deps.js
({ mustDeps: { block: 'i-bem', elem: 'dom' }})
Зависимости
87
bem-bl/blocks-common/i-bem/__dom/i-bem__dom.deps.js
({ mustDeps: { block: 'i-bem' }})
Зависимости
88
bem-bl/blocks-common/i-bem/__dom/i-bem__dom.deps.js
({ mustDeps: { block: 'i-bem' }, shouldDeps: { block: 'i-ecma', elem: 'string' }})
Зависимости
89
bem build --output-name=index --decl=pages/index/index.bemdecl.js --level=bem-bl/blocks-common/ --level=bem-bl/blocks-desktop/ --level=blocks-desktop/ --tech=css --tech=bemhtml --tech=js
Зависимости
90
bem-bl/blocks-desktop/pages/ index/ index.bemdecl.js // декларация
Зависимости
91
bem build --output-name=index --decl=pages/index/index.bemdecl.js --level=bem-bl/blocks-common/ --level=bem-bl/blocks-desktop/ --level=blocks-desktop/ --tech=deps.js
Зависимости
92
bem-bl/blocks-desktop/pages/ index/ index.bemdecl.js // декларация index.deps.js // зависимости
Зависимости
93
bem build --output-name=index --decl=pages/index/index.deps.js --level=bem-bl/blocks-common/ --level=bem-bl/blocks-desktop/ --level=blocks-desktop/ --tech=css --tech=bemhtml --tech=js
Зависимости
94
bem-bl/blocks-desktop/pages/ index/ index.bemdecl.js // декларация index.deps.js // зависимости (сборка) index.js // сборка index.css // сборка index.bemhtml // сборка
Зависимости
95
Зависимости
96
Зависимости
• общие для всех технологий
96
Зависимости
• общие для всех технологий• mustDeps для строгого порядка
96
Зависимости
• общие для всех технологий• mustDeps для строгого порядка• shouldDeps для обеспечения наличия
96
Зависимости
• общие для всех технологий• mustDeps для строгого порядка• shouldDeps для обеспечения наличия• noDeps для отмены зависимостей
96
Библиотеки блоков
Основная часть
/* CSS */.header { font-size: 140%; font-weight: bold;}
Библиотеки блоков
98
<!-- HTML --><h1 class="header"> Заголовок 1</h1>
Библиотеки блоков
99
// BEMHTMLblock header, tag: 'h1'
Библиотеки блоков
100
// JSBEM.DOM.decl( 'header', { /* методы и поля экземпляра */ }, { /* статические методы и поля */ })
Библиотеки блоков
101
<!-- HTML --><h1 class="header i-bem" onclick="return { header: {} }"> Заголовок 1</h1>
Библиотеки блоков
102
// JSBEM.DOM.decl( 'header', { /* методы и поля экземпляра */ }, { live: function() { this.liveBindTo( 'leftclick', function() { this.onClick() } } })
Библиотеки блоков
103
// JSBEM.DOM.decl( 'header', { onClick: function() { ... } }, { live: function() { this.liveBindTo( 'leftclick', function() { this.onClick() } } })
Библиотеки блоков
104
// JSBEM.DOM.decl( 'header', { onClick: function() { this.__base() // метод из библиотеки } })
Библиотеки блоков
105
// JSBEM.DOM.decl( { block: 'header', modName: 'level', modVal: '2' }, { onClick: function() { this.__base() // метод из библиотеки } })
Библиотеки блоков
106
Про что не рассказал
Основная часть
Про что не рассказал
• События, pub-sub
108
Про что не рассказал
• События, pub-sub• Динамическая догрузка JS и CSS
108
Про что не рассказал
• События, pub-sub• Динамическая догрузка JS и CSS• AJAX
108
Про что не рассказал
• События, pub-sub• Динамическая догрузка JS и CSS• AJAX• Сложносоставные блоки
108
Про что не рассказал
• События, pub-sub• Динамическая догрузка JS и CSS• AJAX• Сложносоставные блоки• MVC
108
Заключение
Что было?
Заключение
Что было?
111
Что было?
• способ декларации блоков для клиентского JS
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS• динамическая инициализация и destruct
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS• динамическая инициализация и destruct• ленивая инициализация
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS• динамическая инициализация и destruct• ленивая инициализация• состояния инициализации
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS• динамическая инициализация и destruct• ленивая инициализация• состояния инициализации• БЭМ
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS• динамическая инициализация и destruct• ленивая инициализация• состояния инициализации• БЭМ• файлы и сборка
111
Что было?
• способ декларации блоков для клиентского JS• императивная и декларативная инициализация• параметры из HTML в JS• динамическая инициализация и destruct• ленивая инициализация• состояния инициализации• БЭМ• файлы и сборка• библиотеки блоков
111
Что дальше?
Заключение
Что дальше?
113
Что дальше?
• параллели с собственным опытом
113
Что дальше?
• параллели с собственным опытом– всё примерно так и делаю
113
Что дальше?
• параллели с собственным опытом– всё примерно так и делаю– есть похожие проблемы, не знал как решать
113
Что дальше?
• параллели с собственным опытом– всё примерно так и делаю– есть похожие проблемы, не знал как решать– нет таких проблем
113
Что дальше?
• параллели с собственным опытом– всё примерно так и делаю– есть похожие проблемы, не знал как решать– нет таких проблем
• использовать
113
Что дальше?
• параллели с собственным опытом– всё примерно так и делаю– есть похожие проблемы, не знал как решать– нет таких проблем
• использовать– i-bem.js
113
Что дальше?
• параллели с собственным опытом– всё примерно так и делаю– есть похожие проблемы, не знал как решать– нет таких проблем
• использовать– i-bem.js– реализовать самостоятельно
113
Ссылки
• Разные способы создания клиентских js-компонентовbit.ly/yasubbotnik-msk-js
• БЭМ и JavaScript: Зачем мы написали JS-фреймворк?bit.ly/yasubbotnik-msk-why-i-bem
• БЭМ и JavaScript: Сборник рецептовbit.ly/yasubbotnik-msk-i-bem-cookbook
114
руководитель отделаразработкипоисковых интерфейсов
veged@yandex-team.ru
Спасибо
Сергей Бережной
@veged
github.com/veged