На 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.
До скорого,
Лорен