Upload
yandex
View
689
Download
0
Embed Size (px)
DESCRIPTION
Писать сложный клиентский JavaScript непросто. Каждый, кто пробовал, знает это не понаслышке. Как писать независимые блоки? Как писать блоки, состоящие из других блоков? Как сделать библиотеку блоков? В докладе мы расскажем про то, как упростить себе жизнь и научиться писать клиентский JavaScript в БЭМ-терминах.
Citation preview
руководитель отделаразработки поисковых интерфейсов
Клиентский 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
github.com/veged