Комментарии 20
На $mol меньшей командой за меньший срок можно было бы достигнуть куда большей отзывчивости интерфейса. Причём сразу, а не после жалоб пользователей.
А можно большей командой за больший срок достигнуть результата еще хуже. Ох уж эти «может», такие продажные.
Пожалуйста, уберите эмоционально окрашенный маркетинговый булшит, он не несет полезной нагрузки. Это не помогает лучше понять материал, скорее наоборот, вызывает отторжение и негатив.
Далее вашему представляется текстовая расшифровка одноимённого выступления c IT Global Meetup #1. Вы можете читать её как статью или же открыть в интерфейсе проведения презентаций. Приятного чтения.
Все ссылки в этом абзаце не работают.
$mol — высокоуровневый, но гибкий
Сильное заявление. Собирается $mol только своим сборщиком, UI-компоненты лежат там же в огромном монорепо, ни Bootstrap ни MaterialUI без бубна не заведутся. С данными тоже беда: ни Redux, ни MobX, а свои собственные атомы. Где же обещанная гибкость?
Кусочек проекта перевести не получится, а рисковать переписывать рабочий код целиком $mol, подвергая себя зависимости от одного единственного vintage чревато последствиями, если что-то пойдет не так.
Но да, в mol все свое, основная идея — что все части очень хорошо пригнаны друг к другу. Из коробки сразу все есть, включая UI-библиотеку. Если нужны бутстрапы и пр. — это не к mol.
подвергая себя зависимости от одного единственногоСправедливости ради отмечу, что Винтаж упорный и активно пилит этот мол уже который год. Кстати, первые атомы, которые еще jin, он запилил до MobX, по статьям видно.
А вот с популяризацией своих творений у автора что-то не ладится.
С точки зрения поддержки у него две беды: отсутствие уникального класса у каждого элемента и его неимоверная дубовость. Что мы будем делать, если на одной странице из 20 нам потребуется убрать подзаголовок, на другой добавить после него параграф с описанием, а на третьей выводить имена героев до идентификатора, а не после? Вариантов тут не очень много…
Итак, зачем нам вся эта свистопляска с кучей свойств? Дело в том, что каждое такое свойство — это точка расширения. Мы можем изменить в компоненте любой аспект поведения, просто переопределив соответствующее свойство.
На самом деле эту "уникальную" расширяемость $mol можно применить и к реакт-компонентам если вынести части верстки в методы чтобы потом можно было отнаследоваться и переопределить все что захочется.
Например, тот пример с панелями в вашей статье
$mol_pager $mol_viewer
sub /
< header $mol_viewer
sub < head /
< titler $mol_viewer
sub /
< title
< bodier $mol_scroller
sub < body /
< footer $mol_viewer
sub < foot /
можно было бы записать и на реакте с ничуть не хужей расширяемостью
class $mol_pager extends $mol_viewer {
sub(){
return [
this.header(),
this.bodier()
]
}
header(){
return (
<div>
{this.head()}
{this.titler()}
{this.footer()}
</div>
)
}
head(){ return '' }
titler(){
return <div>{this.title}</div>
}
title(){ return '' }
bodier(){
return <div>{this.body()}</div>
}
body(){ return []}
footer(){
return <div>{this.foot()}</div>
}
foot(){ return []}
}
и потом можно также переопределить все что захочется. Но так никто не делает. Можно сказать что с таким подходом есть проблема в том что много болерплейта и ручной работы а также ненаглядность иерархии композиции из-за чего нужно бродить глазами по методам. $mol это решает тем что вводит новый язык разметки и при этом автоматически генерирует такие классы за программиста, но тоже самое можно было решить добавив во всем знакомый html xml-неймспейсы, чтобы jsx парсер по названию неймспейса сам выносил в методы вложенные части верстки. Тогда бы получилось бы что-то вроде этого
class $mol_pager extends $mol_viewer {
sub(){
return [
<div:header>
<text:head></text>
<div:titler>
<template:title></template>
</div>
</div>,
<div:bodier>
<template:body><template>
</div>,
<div:footer>
<template:foot><template>
</div>
]
}
}
То есть парсер, увидев ':', создаст и перенесет вложенную разметку в метод с таким именем создавая тем самым точку расширения которую можно переопределить через наследование в другом компоненте (template
тег играет роль заглушки для метода с пустым содержимым)
Но так почему-то никто до сих пор не делает и на то скорее всего есть причина в том что в реакт-сообществе наследование, несмотря на гибкие возможности расширения, не приветствуется
<h1>{{title}}</h1>
<h2 *ngIf="subTitleVisible">My Heroes</h2>
<p *ngIf="description">{{ description }}<p>
<ul class="heroes">
<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<ng-template [ngIf]="badgeFirst; else badgeLast">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</ng-template>
<ng-template #badgeLast>
{{hero.name}} <span class="badge">{{hero.id}}</span>
</ng-template>
</li>
</ul>
Так как с html это все будет выглядеть в $mol?
В $mol нет HTML же. Только view.tree:
$my_heroes $mol_view
sub /
<= Title $mol_view
sub / <= title \
<= Title_sub $mol_view
sub / <= title_sub @ \My Heroes
<= Rows $mol_list
rows <= rows /
-
Row!index $mol_row
attr * my_heroes_row_selectd <= selected!index false
event * click!event <=> select!index null
sub <= item_content!index /
<= Badge!index $my_badge
title <= hero_id!index \
<= hero_name!index \
Плюс логика отдельным скриптом.
в целом интересно, но то всё прячется под капот с неясной перспективой отладки и понимания как оно там крутится — это кручинит.
* Сильно отличается от всего того что все знают, тяжело попробовать, надо сначала сломать мозг, потратить кучу? времени, да и синтаксис отпугивает. В том же React можно jsx либо просто js кто не хочет.
* Надо какой-то более плавный вход и быстрый старт, как jQuery — вставил себе кусок кода — заработало, поехал дальше. Минимальная кривая обучения, потому что все что сегодня новое устареет через 2-4 года, (Angular 2 уже устарел, хотя только* вышел). Совсем недавно (сентябрь 2014, всего 3 года назад) самым новомодным был angular 1.2, и где он сейчас?, нужно что-бы было леко запрыгунть на новый фреймворк.
* У вас большой упор в наследование шаблонов, что обычно не нужно (или нужно только для специфических проектов). А оно добавляет сложности.
А тут все внутренности сразу открыты для расширения, причем автоматически. Что можно переопределить, решает не автор компонента, а тот, кто его использует. Захотел что-то поменять в стороннем компоненте — просто унаследуйся и переопредели.
Наследование позволяет те же задачи решать красивее, без рефакторинга исходного компонента и не создавая кучи свойств, без разделения на smart/dumb.
Когда-то я писал View на Backbone, там тоже использовалось наследование, чтобы переопределять отдельные куски разметки. Однако, когда число методов переваливает за 5, да еще и в цепочке наследования не один класс, то легко запутаться, что где происходит.
Ничем не лучше dumb компонентов с кучей разных props. Что тот подход превращает большие view в ад, что этот.
5 в цепочке это что-то много, обычно не надо длинной цепочки. Есть dumb Button в отдельной либе и есть несколько его вариантов в вашем приложении — OkButton, CancelButton, например.
Не делают же HOC(HOC(HOC(Component))), обычно одного обертывания достаточно.
Задачи одинаковые решаются, только на tree-наследовании можно автоматизировать создание методов-точек расширения. Конечно, если не соблюдать принцип подстановки Лисков, то да, наследованием можно очень быстро выстрелить в ногу (был Button, а наследник стал Link или Input).
dumb — простые компоненты, где только представление, обычно чистые функции. Подробнее в статье Presentational and Container Components
.
$mol — лучшее средство от геморроя