На EmberConf 2015 Иегуда Кац и Том Дейл объявили о внесении определенных изменений в Ember 2. В частности, RFC для маршрутизируемых компонентов привлек большое внимание из-за его предложения об устаревании и, в конечном итоге, удалении контроллеров. Естественно, это вызывало тревогу у многих существующих пользователей Ember, тем более что Ember и Sproutcore всегда были клиентскими фреймворками MVC.

Прощай, MVC

Не секрет, что многие новые соглашения и изменения Ember 2 имеют прямое влияние со стороны React и Flux (шаблон потока данных в приложениях React). То, что Flux называет однонаправленным потоком данных, в Ember мы называем данные вниз, действия вверх (DDAU).

DDAU избегает традиционного шаблона MVC на стороне клиента в пользу единого потока данных (следовательно, однонаправленного), что упрощает работу с приложениями и повышает их производительность. Фундаментальная проблема с MVC обнаруживается по мере того, как ваше приложение становится больше и сложнее - каскадные обновления и неявные зависимости приводят к запутанному беспорядку и непредсказуемости. Обновление одного объекта приводит к изменению другого, что, в свою очередь, вызывает больше изменений и, в конечном итоге, затрудняет обслуживание вашего приложения.

В шаблоне DDAU данные передаются в одностороннем порядке, и двусторонние привязки отсутствуют. Различные части вашего приложения могут оставаться полностью изолированными и предсказуемыми, что означает, что вы всегда будете знать источник изменения объекта. Если вы прочитали мой пост о Функциональном программировании и эффекте наблюдателя, вы поймете, почему важно не допускать побочных эффектов в ваших компонентах.

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

Подготовка вашего приложения для DDAU

Когда маршрутизируемые компоненты приземляются, контроллеры будут устаревшими и удалены. Контроллеры и представления всегда сбивали с толку новых пользователей Ember, и 80% их сценариев использования заключались в том, чтобы делать что-то, что по сути было компонентом (посмотрите, как Иегуда и Том объясняют больше в этом видео).

Поскольку компоненты Ember не являются одиночными, они будут демонтированы и повторно обработаны оптимизированным образом, когда Glimmer сочтет это необходимым. Как тогда справиться с сохранением состояния, когда контроллеры уходят?

Например, у вас может быть какое-то свойство на вашем контроллере, которое хранит состояние, которое вы хотели бы сохранить во всем приложении. Для этого в Ember 2 (и сегодня) мы можем удалить это свойство контроллера в пользу «компонентов с поддержкой служб». Служба будет сохранять одноэлементное состояние компонента и явно вводиться только там, где это необходимо. Поскольку сервисы мощные и ими легко злоупотреблять, я расскажу об этом подробнее в конце этого поста.

Реализация компонентов с поддержкой служб

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

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

В шаблоне маршрута мы можем просто отобразить состояние внедренной службы с помощью помощника each.

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

Как уже упоминалось, сама услуга проста. Позже мы можем определить более сложное поведение, но лежащая в основе постоянство его состояния - это просто массив JavaScript.

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

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

Помощник contains не поставляется с Ember, но сама функция представляет собой одну строку кода. Существует множество полезных надстроек, которые добавляют такие помощники в ваше приложение - например, ember-true-helpers - это надстройка, которую я использую почти во всех своих приложениях.

Как упоминалось в моем предыдущем посте, аддон ember-one-way-input - это простой способ начать использовать односторонние привязки сегодня.

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

Предупреждение об услугах

Как говорится, «с большой силой…». Поскольку сервисы в Ember являются одиночными, возникает соблазн создать несколько сервисов и внедрить их повсюду.

Если ваша основная причина для создания службы - использовать ее как глобальную, это, как правило, запах кода, потому что зависимости становятся неявными (мы узнали ранее, что это плохо), и части вашего приложения становятся тесно связанными. Вместо этого предоставляйте данные и действия через интерфейсы, чтобы ваш код оставался несвязанным и явным. Помните принцип наименьшей мощности и используйте услугу только в случае крайней необходимости!

Итак, когда мне следует использовать Сервис?

Мне нравится этот ответ о переполнении стека о том, когда следует использовать синглтон. По сути, вы должны использовать только один, когда у вас может быть только один экземпляр во всем приложении. Например, корзина покупок, мгновенные сообщения или лента действий могут быть отличными кандидатами на услугу.

Спасибо за прочтение! В следующем посте из этой серии мы рассмотрим другие продвинутые техники паттерна DDAU.

До скорого,

Лорен