Как стать автором
Обновить

Ember: Декларативная шаблонизация c компонируемыми хелперами

Время на прочтение 5 мин
Количество просмотров 3.4K
Автор оригинала: Lauren Tan

Ранее, я упоминала, что помощники (Helper) Ember'а были введены в версии 1.13. На мой взгляд, помощники одни из самых полезных, но не часто обсуждаемых, функций Ember.


В моей лекции Idiomatic Ember на EmberConf 2016, я в деталях рассказала о хелперах, показывая, как они могут быть использованы для подключения и существенного расширения функционала Handlebars.
Они могут использоваться для декларативной шаблонизации — стиля шаблонизации использующего компонируемые действия (composing actions), и предоставляя шаблонам больше ответственности в отношении презентационный логики.


Вместе с коллегой Marten Schilstra, из DockYard, мы создали аддон ember-composable-helpers. Это пакет декларативных помощников, и с его помощью можно уменьшить количество шаблонного кода в Вашем приложении. Вы можете установить его так:


ember install ember-composable-helpers

Один из моих любимых помощников в аддоне — pipe (и его closure версия, pipe-action). Он позволяет декларативно составлять действия в шаблоне, вместо создания множества вариантов в компоненте:


{{perform-calculation
    add=(action "add")
    subtract=(action "subtract")
    multiply=(action "multiply")
    square=(action "square")
}}

{{! perform-calculation/template.hbs }}
<button {{action (pipe add square) 2 4}}>Should be 36</button>
<button {{action (pipe subtract square) 4 2}}>Should be 4</button>
<button {{action (pipe multiply square) 5 5}}>Should be 625</button>

Помощник pipe был вдохновлён оператором pipe Elixir'а (|>), который позволяет написать следующее:


A(B(C(D(E), "F"), "G"), "H")

Как цепочка преобразователей:


E
|> D()
|> C("F")
|> B("G")
|> A("H")

Используя pipe оператор, можно естественным образом выразить как E передаётся функции D, затем полученное значение передаётся C в качестве первого аргумента, и так далее. Я думаю, мы можем согласиться, что pipe версия намного легче для чтения!


Если бы Вы только знали мощь хелперов


Вы можете подумать, что помощник это примитивная KeyWord конструкция, использующая Ember и HTMLBars для расширения выражений, предоставленных Handlebars.
На самом базовом уровне, Handlebars отвечает за компиляцию hbs шаблонов в HTML:


<p>{{myText}}</p>
<!-- скомпилируется в: -->
<p>Hello world!</p>

Ember и HTMLBars строится поверх этого, добавляя полезные выражения вроде action, mut, get, и hash. На самом деле, все знакомые хелперы, которые вы используете (от each до component) являются частью HTMLBars!


Ember Helpers работают на более высоком уровне, чем HTMLBars helpers, и могут быть использованы для создания новых выражений в Ember, позволяя эффективно расширить шаблонизацию с собственным поведением.


Всё зависит от обстоятельств


Более опытные или консервативные разработчики могли бы посчитать это опасным: при всей своей полезности для конечных пользователей, он также может открыть возможности для злоупотреблений.


Для примера, в Elixir, макросы могут быть использованы для расширения языка, но не рекомендуется для реального использования. Это было закреплено в отличной книге Chris McCord Метапрограммирование на Elixir – "Правило 1: Не используйте макросы".


К счастью, помощники не настолько мощные как макросы Elixir, и играют важную роль в модели программирования Ember. В отличии от макросов, которые позволяют достучаться до AST, использование Ember помощника для расширения презентационной логики приемлемо пока мы не злоупотребляем этим, и это та особенность, где опыт вступает в игру. Так что используйте хелперы с умом.


Уберите прочь Вашу логику с моего газона


Некоторые люди могут испытывать дискомфорт при использовании аддонов, содержащих помощники, из-за неправильного представления о том, что они привносят слишком много логики в шаблоны, и предпочитают держать их свободными от неё.


В качестве лучшей практики, мы должны воздержаться от сложной логики в шаблонах, а также использования вложенных конструкций вроде этой:


{{#unless (or (and (gte value 0) (lt value 0.0001))
              (and (lt value 0) (not allowNegativeResults)))}}
  ...
{{/unless}}

Вместо этого используйте вычисляемые свойства (computed property).


В то же время, сохранять свои шаблоны на 100% свободными от логики очень тяжело – Вы, вероятнее всего уже используете логические помощники вроде if/else или unless. Можно легко упустить из виду тот факт, что количество логики в шаблоне строго не определено.


Назад в будущее


ember-composable-helpers, на самом деле, не значительно увеличит количество логики в шаблонах, если правильно использовать, он инкапсулирует логику представления внутрь этих помощников, и во многих случаях может помочь Вам ликвидировать избыточный код в компонентах или контроллерах.


Например, Вы могли бы написать что-то подобное в вашем приложении:


import Ember from 'ember';

const {
  Component,
  computed: { filterBy, setDiff },
  set
} = Ember;

export default Component.extend({
  activeEmployees: filterBy('employees', 'isActive'),
  inactiveEmployees: setDiff('employees', 'activeEmployees')
});

Довольно распространённая практика, иметь "компонент-посредник" для использования в других компонентах. С помощью ember-composable-helpers можно писать такие конструкции непосредственно в шаблоне, где всё абсолютно понятно:


<h2>Active Employees</h2>
{{#each (filter-by "isActive" engineers) as |employee|}}
  {{employee.name}} is active!
{{/each}}

<h2>Inactive Employees</h2>
{{#each (reject-by "isActive" engineers) as |employee|}}
  {{employee.name}} is inactive!
{{/each}}

Вы можете думать о компонируемых помощниках как своего рода вычисляемых макро свойствах, которые можно использовать и создавать непосредственно в шаблоне. И поскольку Вы можете создавать суб-выражения в Ember, они могут стать мощной конструкцией для уменьшения шаблонного кода в приложении.


С учетом выше сказанного, помните, не слишком увлекайтесь глубокой вложенностью!


Лучшее решение


Как и любые другие инструменты программирования, важно проявлять здравый смысл и использовать их с умом.


Если Вы можете что-то сделать, не значит, что вы должны.

Хорошо написанный уровень представления(view layer) означает, что шаблоны должны быть декларативными (всё совершенно очевидно), насколько это возможно, а не то, что мы должны избегать логики вообще.
Тем не менее, мы не выступаем за перемещение всей своей логики в шаблон — опять же, количество логики в шаблоне строго не регламетировано.


Если Вы хотите увидеть, как аддон используется, Katherin Siracusa написала отличную статью о том, как она использует ember-composable-helpers в AlphaSights:


Данный паттерн позволяет выполнять операции над данными и в далнейшем более вспомогательные, краткосрочные действия, постоянно возникающие в нашем приложении. Используя компонируемые хелперы, мы можем сделать это довольно просто, без особого дублирования и, не беспокоясь о нежелательных побочных эффектах.

Вы также можете принять участие в обсуждении на нашем Slack канале #e-composable-helpers.


Как всегда, спасибо за внимание!

Теги:
Хабы:
+9
Комментарии 0
Комментарии Комментировать

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн