Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Владимир Гриненко
Search
FrontFest
November 21, 2017
Programming
730
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Владимир Гриненко
FrontFest
November 21, 2017
More Decks by FrontFest
See All by FrontFest
Тим Чаптыков
frontfest
0
1.2k
Егор Банщиков
frontfest
0
890
Jose M. Perez
frontfest
0
750
Алексей Иванов
frontfest
0
1.4k
Екатерина Пригара
frontfest
0
710
Léonie Watson
frontfest
0
770
Кирилл Чернышев
frontfest
0
770
Виктор Грищенко
frontfest
0
660
Игорь Алексеенко
frontfest
0
500
Other Decks in Programming
See All in Programming
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
860
Claude Team Plan導入・ガイド
tk3fftk
0
210
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
170
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
130
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
AI 輔助遺留系統現代化的經驗分享
jame2408
1
1.2k
型も通る、synthも通る、それでも危ない 〜AIのCDKの権限とコストを機械で検証する〜 / It Passes Type Checks, It Passes Synth Checks, but It’s Still Risky — Automatically Verifying Permissions and Costs in AI’s CDK —
seike460
PRO
1
340
5分で問診!Composer セキュリティ健康診断
codmoninc
0
280
ローカルLLMでどこまでコードが書けるか -縮小版 / How much code can be written on a local LLM Shortened
kishida
2
190
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
220
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
6.2k
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
37
7.4k
Context Engineering - Making Every Token Count
addyosmani
9
1k
Six Lessons from altMBA
skipperchong
29
4.3k
First, design no harm
axbom
PRO
2
1.2k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
630
Abbi's Birthday
coloredviolet
3
8.7k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
260
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
180
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
530
Marketing to machines
jonoalderson
1
5.6k
Transcript
Декларативная шаблонизация Владимир Гриненко руководитель службы
Декларативность
Декларативное программирование — это парадигма программирования, в которой задается спецификация
решения задачи, то есть описывается, что представляет собой проблема и
4
Императивно
document Императивно 6
document .querySelectorAll('.link') Императивно 7
document .querySelectorAll('.link') .forEach(link => link.style.color = 'red'); Императивно 8
document .querySelectorAll('.link') .forEach(link => link.style.color = 'red'); document.body.innerHTML += '<a
class="link" href="http://2017.frontfest.ru">FrontFest</a>'; Императивно 9
document .querySelectorAll('.link') .forEach(link => link.style.color = 'red'); document.body.innerHTML += '<a
class="link" href="http://2017.frontfest.ru">FrontFest</a>'; Императивно 10 document.querySelector('.link').classList.remove('link');
Декларативно
.link { color: red } Декларативно 12
library/components/link.css .link { color: red } Декларативно 13 project/components/link.css .link
{ text-decoration: none }
$('.btn').click(function() { $(this) .toggleClass('btn_disabled') .text( $(this).text() === 'Enable' ? 'Disable'
: 'Enable' ); }); Императивно 14
<Btn onToggleDisabled={this.handleToggleDisabled} disabled={this.state.disabled}> {this.state.buttonText} </Btn> Декларативно 15
Шаблонизация
<div class="user"> Elizabeth </div> Шаблонизация 17
<div class="user"> <?php echo $username; ?> </div> Шаблонизация 18
const html = `<div class="user">${username}</div>`; Шаблонизация 19
20
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-
haspopup="true" aria-expanded="false"> Dropdown button </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <a class="dropdown-item" href="#">Action</a> <a class="dropdown-item" href="#">Another action</a> <a class="dropdown-item" href="#">Something else here</a> </div> </div> Шаблонизация 21
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-
haspopup="true" aria-expanded="false"> <?php echo $buttonText; ?> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <?php for ($i = 1; $i <= count($items); $i++) { ?> <a class="dropdown-item" href="<?php echo $items[$i] ["href"]; ?>"><?php echo $items[$i]["text"]; ?></a> <?php } ?> </div> </div> Шаблонизация 22
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-
haspopup="true" aria-expanded="false"> <?php echo $buttonText; ?> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <?php for ($i = 1; $i <= count($items); $i++) { ?> <a class="dropdown-item" href="<?php echo $items[$i] ["href"]; ?>"><?php echo $items[$i]["text"]; ?></a> <?php } ?> </div> </div> Шаблонизация 23
Проблемы 24 〉Много писать 〉Много исправлять 〉Невозможно обновиться автоматически
const html = `<div class="user">${username}</div>`; Шаблонизация 25
render() { return ( <div className="user"> {this.props.username} </div> ); }
Компонентный подход 26
<User username="Elizabeth"/> Компонентный подход 27
Проблемы решены 28 〉Много писать 〉Много исправлять 〉Невозможно обновиться автоматически
render() { return ( <div className="user"> {this.props.username} </div> ); }
Еще проблемы 29
render() { return ( <div className="user"> {this.props.hasIcon && <Icon/>} {this.props.username}
</div> ); } Еще проблемы 30
library/components/link.css .link { color: red } Декларативно 31 project/components/link.css .link
{ text-decoration: none }
32
Больше декларативности!
XML + XSLT
<User username="Elizabeth"/> <User username="Elizabeth II" hasIcon="true"/> XML + XSLT 35
<xsl:template match="User"> <div class="user"> <xsl:apply-templates/> <xsl:apply-templates select="@username"/> </div> </xsl:template> XML
+ XSLT 36
<xsl:template match="User[hasIcon=true]"> <xsl:apply-templates select="Icon"/> </xsl:template> XML + XSLT 37
BEMJSON + BEMHTML
{ block: 'user', username: 'Elizabeth' } Полная декларативность 39
{ block: 'user', username: 'Elizabeth' } Полная декларативность 40 <div
class="user"></div>
block('user').content()(node => node.ctx.username); Полная декларативность 41
block('user').content()(node => node.ctx.username); block('user') .match()(node => node.ctx.hasIcon) .content()(node => [
{ block: 'icon' }, applyNext() ]); Полная декларативность 42
block('user').content()(node => node.ctx.username); block('user') .match()(node => node.ctx.hasIcon) .content()(node => [
{ block: 'icon' }, applyNext() ]); Полная декларативность 43
block('user').content()(node => node.ctx.username); block('user') .match()(node => node.ctx.hasIcon) .content()(node => [
{ block: 'icon' }, applyNext() ]); Полная декларативность 44
block('data')( tag()('ul'), elem('item').tag()('li') ); Полная декларативность: теги 45
block('data')( tag()('table'), content()(() => ({ tag: 'tr', content: applyNext() })),
elem('item').tag()('td') ); Полная декларативность: теги 46
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-
haspopup="true" aria-expanded="false"> Dropdown button </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <a class="dropdown-item" href="#">Action</a> <a class="dropdown-item" href="#">Another action</a> <a class="dropdown-item" href="#">Something else here</a> </div> </div> Полная декларативность: реальный пример 47
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-
haspopup="true" aria-expanded="false"> <?php echo $buttonText; ?> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <?php for ($i = 1; $i <= count($items); $i++) { ?> <a class="dropdown-item" href="<?php echo $items[$i] ["href"]; ?>"><?php echo $items[$i]["text"]; ?></a> <?php } ?> </div> </div> Полная декларативность: реальный пример 48
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-
haspopup="true" aria-expanded="false"> <?php echo $buttonText; ?> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <?php for ($i = 1; $i <= count($items); $i++) { ?> <a class="dropdown-item" href="<?php echo $items[$i] ["href"]; ?>"><?php echo $items[$i]["text"]; ?></a> <?php } ?> </div> </div> Полная декларативность: реальный пример 49
block('dropdown')( content()(node => [ { block: 'btn', mods: { secondary:
true }, mix: 'dropdown-toggle', attrs: { type: 'button', id: 'dropdownMenuButton', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false } }, { elem: 'menu', attrs: { 'aria-labelledby': 'dropdownMenuButton' }, content: applyNext().map(item => ({ elem: 'item', url: item.url, content: item.text })) } ]), Полная декларативность: реальный пример 50 elem('item').replace()(node => ({ block: 'link', mix: node.ctx, url: node.ctx.url, content: node.ctx.content })) )
{ block: 'dropdown', content: [ { elem: 'item', url: 'http://site1.com',
text: 'Site1' }, { elem: 'item', url: 'http://site2.com', text: 'Site2' }, { elem: 'item', url: 'http://site3.com', text: 'Site3' } ] } Полная декларативность: реальный пример 51
const css = require('./css.json'), visited = {}; block('*') .match()(node =>
!visited[node.block]) .replace()(node => { visited[node.block] = true; return [ css[node.block], this.ctx ]; }); Полная декларативность: любой узел 52
53 bem.github.io/bem-xjst
54 github.com/bem/bh-php
$bh->match('button', function ($ctx) { $ctx->tag('button'); }); bh.php 55
Синтаксис может быть любым
React
bem-react-core
Что это 59 〉Обертка над стандартными React-компонентами 〉Полностью совместимая со
стандартными компонентами 〉Не требует знания БЭМ 〉Не требует использования модификаторов 〉Не требует использования уровней переопределения
Что это 60 〉Автоматизирует генерацию классов 〉Позволяет использовать элементы, модификаторы
и миксы 〉Позволяет использовать уровни переопределения 〉Оперирует компонентами, а не путями
None
<div class="user"> Elizabeth </div> Пример 62
export default class User extends Component { render() { return
( <div className="user">{this.props.username}</div> ); } } Было 63
import {decl} from 'bem-react-core'; export default decl({ block: 'user', content({username})
{ return username; } }); Стало 64
export default decl({ block: 'User', willMount() {}, didMount() {}, willReceiveProps()
{}, shouldUpdate() {}, willUpdate() {}, didUpdate() {}, willUnmount() {} }); Livecycle-методы 65
import User from 'b:user'; ReactDOM.render( <User />, //... ); Импорт
66
var User = [ require('path/to/user/user.js') ][0].applyDecls(); ReactDOM.render(<User />); Импорт 67
Траншпилеры 68 〉webpack-bem-loader 〉babel-plugin-bem-import
Какие проблемы решает bem-react-core
Какие проблемы 70 〉Модификации бывают опциональными › отдельные файлы ›
можно выразить через class ButtonWithIcon extends Button
Какие проблемы 71 〉Модификации бывают опциональными 〉Композитные модификации › пересечение
всех вариантов не выражается через наследование › Button, Button_compound, Button_with-icon
import { BaseComponent, warn } from '../../Utilities'; import { ButtonType,
IButtonProps } from './Button.Props'; import { DefaultButton } from './DefaultButton/DefaultButton'; import { CommandButton } from './CommandButton/CommandButton'; import { CompoundButton } from './CompoundButton/CompoundButton'; import { IconButton } from './IconButton/IconButton'; import { PrimaryButton } from './PrimaryButton/PrimaryButton'; Например, кнопка 72 github.com/OfficeDev/office-ui-fabric-react
public render() { const props = this.props; switch (props.buttonType) {
case ButtonType.command: return <CommandButton { ...props } />; case ButtonType.compound: return <CompoundButton { ...props } />; case ButtonType.icon: return <IconButton { ...props } />; case ButtonType.primary: return <PrimaryButton { ...props } />; default: return <DefaultButton { ...props } />; } } Например, кнопка 73
<Button compound primary icon="check"></Button> А теперь с bem-react-core 74 Декларативно!
// Button_type_compound.js import {declMod} from 'bem-react-core'; import React from 'react';
export default declMod(({ type }) => type === 'button', { block: 'Button', mods({ type }) { return { ...this.__base.apply(this, arguments), type }; }, content() { return <Button … /> } }); Модификатор 75
import Button from 'b:Button m:type=compound'; <Button type="compound">my button</Button> Модификатор 76
None
Шаблонизация в bem-react-core 78 〉tag 〉attrs 〉mods 〉cls 〉mix 〉content
Уровни переопределения
Для чего 80 〉Общая библиотека и проекты
Для чего 81 〉Общая библиотека и проекты lego serp images
video news
Для чего 82 〉Общая библиотека и проекты 〉Платформы
Для чего 83 〉Общая библиотека и проекты 〉Платформы common desktop
touch
Для чего 84 〉Общая библиотека и проекты 〉Платформы common desktop
touch pad phone
Для чего 85 〉Общая библиотека и проекты 〉Платформы 〉Дизайн
Для чего 86 〉Общая библиотека и проекты 〉Платформы 〉Дизайн 〉Эксперименты
experiments exp1 exp2 exp3
None
library/components/link.css .link { color: red } Как это работает 88
project/components/link.css .link { text-decoration: none }
[ 'path/to/level1', 'path/to/level2' ] Уровни переопределения 89
/* styles.css */ @import path/to/level1/block1/block1.css; @import path/to/level2/block1/block1.css; Уровни переопределения 90
// blocks/Link/Link.js import decl from 'bem-react-core'; export default decl({ block:
'Link', tag: 'a', attrs(({url}) => ({href: url})) }); <Link url="…">… <a class="Link" href="…">… Уровни переопределения 91
// blocks/Link/Link.js // a11y/blocks/Link/Link.js import decl from 'bem-react-core'; export default
decl({ block: 'Link', attrs() { return { ...this.__base.apply(this, arguments), role: 'link' }; } } <Link url="…">… <a class="Link" href="…" role="link">… Уровни переопределения 92
None
94 github.com/bem/bem-react-core
95 Пишите декларативно!
None
Вопросы?
None
Владимир Гриненко
[email protected]
tadatuta tadatuta tadatuta