BEViS& bt
Smarty, Django и т.п.
контроллер шаблоныпредставления
HTML
< / >
HTTP Server
3
BEViS
index.page.js
index.bt.js
HTML
< / >
HTTP Server
4
BEViS controllerpages.declare('index', function () {
return [
{ block: 'header' },
{ block: 'authorization' }
];
});
01.
02.
03.
04.
05.
06.
5
И.И.Шишкин, К.А.Савицкий«Утро в сосновом бору»
1889
Простой JSON[
{ block: 'header' },
{ block: 'authorization' }
]
01.
02.
03.
04.
Сложный HTML<div class="header">
<a class="header__logo" href="/">
<img src="logo.png">
</a>
<h1 class="header__title">Демо-страница</h1>
<h2 class="header__slogan">Слоган</h2>
<a class="header__rss" href="/?rss">
<img src="rss.png">
</a>
</div>
<form class="authorization" action="/?task=login">
<label class="authorization__label">Логин</label>
<input class="authorization__login" value="">
<label class="authorization__label">Пароль</label>
<input class="authorization__password"
value="" type="password">
<button class="authorization__submit">
Войти
</button>
</form>
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
9
Одного имени
достаточно
Имя блока{
друг: 'Марат'
}
01.
02.
03.
11
Необязательные параметры{
суп: 'солянка',
сметанаНужна: 'да'
}
01.
02.
03.
04.
12
Создавать страницы - просто!{
block: 'header',
showSearch: true
}
01.
02.
03.
04.
13
Блок - это1. HTML-cтруктура
2. CSS-представление
3. JS-поведение
14
HTML
Императивные шаблоны<p>Уважаемый {{ person }}</p>
<p>Ваш заказ от {{ date:"F j, Y" }} принят на обработку.</p>
<p>Пожалуйста, убедитесь, что всё выбрано верно:</p>
<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
<p>Гарантия - 12 месяцев.</p>
{% else %}
<p>Со всеми неполадками обращайтесь в наш сервиcный центр.</p>
{% endif %}
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
15.
16
Smarty
контроллер императивныешаблоны
HTML
< / >
HTTP Server
17
Smarty
index.php index.tpl.php
HTML
< / >
HTTP Server
18
Декларативные
шаблоны
Что это?h1 {
color: red;
}
01.
02.
03.
20
Исходный JSONpages.declare('index', function () {
return {
block: 'header'
}
});
Финальный HTML<div class="header">
</div>
01.
02.
03.
04.
05.
01.
02.
21
Абстрактный декларативный шаблонheader {
tag: div;
}
01.
02.
03.
22
Абстрактный декларативный шаблонheader {
tag: div;
}
Реальный декларативный шаблонbt.match('header', function (ctx) {
ctx.setTag('div');
});
01.
02.
03.
01.
02.
03.
23
Делаем шаблон умнееbt.match('header', function (ctx) {
ctx.setTag('div');
ctx.setContent({ // Генерим внутри шапки новый JSON
elem: 'title', // создаём элемент title в содержимом
titleText: 'CodeFest 2014' // параметром передаём в него текст
});
});
01.
02.
03.
04.
05.
06.
07.
24
Делаем шаблон умнееbt.match('header', function (ctx) {
ctx.setTag('div');
ctx.setContent({
elem: 'title',
titleText: 'CodeFest 2014'
});
});
bt.match('header__title', function (ctx) {
ctx.setTag('h1');
ctx.setContent(
ctx.getParam('titleText')
);
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
25
Результат<div class="header">
<h1 class="header__title">CodeFest 2014</h1>
</div>
01.
02.
03.
26
Простой JSON{
block: "y-header",
view: "islet-search",
showSearch: true,
showSuggest: true
}
01.
02.
03.
04.
05.
06.
07.
27
Простой JSON{
block: "y-header",
view: "islet-search",
showSearch: true,
showSuggest: true
}
01.
02.
03.
04.
05.
06.
07.
Сложный HTML<header class="y-header_islet-search _init _live-events" data-block="y-header" data-options="{"mixins":[{"name":"location-form"}]}">
<div class="y-header_islet-search__wrapper">
<a class="y-header_islet-search__logo _lang_ru" href="http://www.yandex.ru">
<img class="y-header_islet-search__logo-img" alt="Яндекс" src="//yandex.st/lego/_/X31pO5JJJKEifJ7sfvuf3mGeD_8.png">
</a>
<div class="y-header_islet-search__info">
<span class="y-header_islet-search__board-call">
<a class="y-button_islet-board _init" data-block="y-button" role="button" href="http://www.yandex.ru/all">
<span class="y-button_islet-board__icon">
<div class="y-header_islet__board-call-icon"></div>
</span>
</a>
</span>
</div>
<div class="y-header_islet-search__arrow">
<form class="y-header_islet-search__form _live-events" action="/">
<div class="y-header_islet-search__button">
<button class="y-button_islet _init" data-block="y-button" tabindex="2" type="submit"><span class="y-button_islet__text">Найти</span></button>
</div>
<div class="y-header_islet-search__input">
<div class="y-suggest_islet _init" data-block="y-suggest"
data-options="{"options":{"suggestDropOptions":{"view":"islet-header","suggestDropItemView":"islet-header"},"dataProviderOptions":{"queryParams":{"lang":"ru-RU","search_type":"all","fullpath":1,"v":5},"posQueryParamName":"pos","textQueryParamName":"part","disableGrouping":true}},"mixins":[{"name":"header-suggest-configurer"}]}">
<span class="y-input_islet-label-icons _init" data-block="y-input"><span class="y-input_islet-label-icons__label"><a class="y-input_islet-label-icons__label-link" href="/">Карты</a></span><span
class="y-input_islet-label-icons__icons"><span class="y-input_islet-label-icons__close-small"></span></span><span class="y-input_islet-label-icons__context"><input
class="y-input_islet-label-icons__control" id="uniq0" name="text" value="" autocomplete="off"></span></span>
<div class="y-suggest-drop_islet-header" data-block="y-suggest-drop" data-options="{"options":{"wide":true}}"></div>
</div>
</div>
</form>
</div>
</div>
<div class="y-header_islet-search__board"></div>
</header>
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
28
{ block: 'y-header',
view: 'islet-search', showBoard: true, serviceName: 'Карты', searchQuery: 'Новосибирск'}
Карты НайтиНовосибирск
Чем декларативные шаблоны лучше?1. Даже в большом проекте остаются простыми
2. Гарантируют внешнее API блока
BEViS - это как Web Components, только работает уже сегодня ;)
30
CSS
Мы так не делаем<div class="header authorization">
</div>
01.
02.
32
Г.Данелия, 1977В.Кикабидзе
«Мимино»
View{
block: "header",
view: "search"
}
Финальный HTML<div class="header_search">
</div>
01.
02.
03.
04.
01.
02.
34
Кто-то пишет так<div class="button button_theme_normal button_shadow_yes">
нажми меня
</div>
01.
02.
03.
35
Бивис делает иначе<div class="button_normal-shadow">
нажми меня
</div>
01.
02.
03.
36
Простой JSON{
block: "button",
view: "normal-shadow"
}
Простой HTML<div class="button_normal-shadow">
нажми меня
</div>
01.
02.
03.
04.
01.
02.
03.
37
CSS-
препроцессор
Публичные селекторы.button {
skin-common();
skin-theme-normal();
}
.button_normal-shadow {
skin-common();
skin-theme-normal();
skin-shadow();
}
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
39
Публичные селекторы.button {
skin-common();
skin-theme-normal();
}
.button_normal-shadow {
skin-common();
skin-theme-normal();
skin-shadow();
}
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
Приватные функцииskin-common() {
/* общие стили кнопки */
}
skin-theme-normal() {
/* цвета кнопки */
}
skin-shadow() {
/* тень под кнопкой */
}
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
40
Все конфликты под контролем.button {
skin-common();
skin-theme-normal();
/* а здесь разрулил все конфликты этих миксинов */
}
.button_normal-shadow {
skin-common();
skin-theme-normal();
skin-shadow();
/* а здесь разрулил все конфликты этих миксинов */
}
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
41
JS
В маленьких проектах$(document).ready(function() {
var form = $('#my-form');
form.submit(onSubmited);
function onSubmited() {
if ($('#my-form .button').hasClass('disabled')) {
return false;
}
}
});
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
43
В маленьких проектах с модулямиmodules.define(
'form',
['jquery'],
function(provide, $) {
var form = $('#my-form');
form.submit(onSubmited);
function onSubmited() {
if ($('#my-form .button').hasClass('disabled')) {
return false;
}
}
provide(form);
}
);
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
15.
16.
44
Бивис = Модуль + YBlock-классmodules.define(
'form',
['y-button', 'y-block'],
function(provide, YButton, YBlock) {
var Form = inherit(YBlock, {
__constructor: function () {
this._submitButton = YButton.find(this);
this._bindTo(this.getDomNode(), 'submit', this._onSubmitted);
},
_onSubmitted: function (e) {
if (this._submitButton.isDisabled()) {
e.preventDefault();
} else {
this.emit('submit');
}
}
});
provide(Form);
}
);
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
45
Бивис = Модуль + YBlock-класс1. Код можно реиспользовать
2. Мы управляем абстракциями, а не DOM-объектами
46
Поведение отделено от отображения<div
class="header"
data-block="header">
</div>
01.
02.
03.
04.
47
Состояние блока<input class="login _unfilled" type="text"/>
/* обычное состояние */
.login {
...
}
/* тревожное состояние */
.login._unfilled {
border: 1px solid red;
}
01.
02.
01.
02.
03.
04.
05.
06.
07.
08.
09.
48
BlockElementViewState
Файлы и сборка
Файлыblocks/
form/
form.styl
form.js
form.bt.js
header/
header.styl
header.js
header.bt.js
01.
02.
03.
04.
05.
06.
07.
08.
09.
51
Быстрый стартgit clone [email protected]:bevis-ui/bevis-stub.git your-project
cd your-project
make
01.
02.
03.
55
BEViS
• Полноценный сайт на обычном JS
• Покрыт юнит-тестами на 100%
• Написан в понятном Сode Style
Это серьёзный инструмент с добрым лицом ;)
58
(: Спасибо ;)
BEViS & bt• Презентация — bevis-ui.github.io/bevis-and-bt-speech
• TODO MVC — github.com/bevis-ui/bevis-todo
• Blog Engine — github.com/bevis-ui/bevis-blog
• Документация — github.com/bevis-ui/docs
• bt — github.com/enb-make/bt
• ENB — github.com/enb-make/enb
• ENB-конфигуратор — enb-make.info/config
Марат Дулин• [email protected]
• twitter.com/mdevils
• github.com/mdevils
Вадим Макишвили• [email protected]
• makishvili.com
60
Top Related