Aurelia — это JavaScript-фреймворк нового поколения. Один из аспектов, который делает его фреймворком следующего поколения, заключается в том, что он делает упор на создание приложений из повторно используемых компонентов небольшого размера (похожих в этом смысле на React и Angular2). Компоненты создаются в Aurelia путем создания пары View и View-Model, где представление представляет собой шаблон HTML, соответствующий стандартам, а ViewModel — файл ES-Next или Typescript. По соглашению представление и модель представления имеют одно и то же имя файла (без расширения).

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

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

Для этого я считаю полезным задать следующие вопросы:

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

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

Я кратко изложу некоторые инструменты и методы, которые предоставляет Aurelia, и объясню, что может означать, что следует выбрать тот или иной вариант.

Привязка данных

Система привязки данных Aurelia позволяет передавать данные из модели представления в представление (в случае односторонней привязки данных) и обратно (в случае двусторонней привязки данных). Привязка данных действительно эффективна в простых ситуациях, таких как:

View-Model для просмотра

Установите свойство в модели представления, которое должно быть прочитано представлением.

Прочитайте свойство в представлении с интерполяцией строк Aurelia и отобразите его в теге h1.

Менее очевидный способ использования системы привязки данных Aurelia — передача данных от родительского компонента к дочернему компоненту, как показано на следующей диаграмме:

Мы можем сделать это, превратив наш hello view + view-model в greeter CustomElement (основной вариант для создания веб-компонентов с помощью Aurelia):

Мы объявляем свойство в корневой модели представления с именем parentGreeting, снова задавая его в конструкторе. Затем мы привязываем это свойство к свойству greeting в дочерней модели представления:

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

– Что, если мы не всегда хотим, чтобы значение от родителя напрямую отфильтровывалось до дочерних элементов? Например, мы хотим, чтобы дочерние элементы получали обновление только при определенном событии, таком как нажатие кнопки Сохранить.
— Как мы уведомляем родительский компонент об изменении значения в дочернем?< br /> — Если значение обновляется в дочернем элементе, следует ли сохранять это значение в самом хранилище данных/веб-API? Как родитель узнает, что ему нужно повторно получить состояние из веб-API и повторно отобразить себя?

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

Введите агрегатор событий.

Агрегатор событий

Агрегатор событий — это простой элемент косвенности. В простейшей форме он регистрируется со всеми интересующими вас исходными объектами, а все целевые объекты регистрируются в агрегаторе событий. Агрегатор событий реагирует на любое событие исходного объекта, распространяя это событие на целевые объекты.

Мартин Фаулер

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

Это выглядит примерно как на схеме ниже:

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

Например, в приложении для обмена сообщениями у вас могут быть компоненты messageComposer, messageList и компонент messageBell:

Когда составление нового сообщения завершено, событие new-message должно быть опубликовано в EventAggregator. Затем компоненты messageBell и messageList могут подписаться на это событие и отреагировать соответствующим образом:

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

Итак, если messageComposer отвечает за создание нового сообщения, отвечает ли он также за сохранение этого сообщения? Что, если с сообщением нужно сделать что-то еще, прежде чем оно будет отправлено на сервер? На данный момент естественным расширением приведенного выше шаблона является переход к архитектуре под названием Data-Down, Actions Up, которая возникла в сообществе Ember.js, на которое, в свою очередь, повлияли Flux/ Шаблон однонаправленного потока данных Redux от React.

Данные вниз Действия вверх

Data-Down, Actions Up — это простое практическое правило того, как структурировать коммуникацию в сложных приложениях, основанных на компонентах. Данные передаются от родительского компонента к дочерним компонентам (аналогично тому, что мы видели в первом примере привязки данных). Действия (события EventAggregator в мире Aurelia) затем передаются обратно родительскому объекту, чтобы можно было принять решение:

Расширяя наш пример приложения для обмена сообщениями из приведенного выше, мы можем следовать этому практическому правилу, создав новый компонент корневого уровня с именем messages. Этот компонент отвечает за получение списка сообщений из веб-API и сохранение любых изменений обратно:

Этот компонент будет передавать данные своим дочерним компонентам, используя одностороннюю привязку данных, а дочерние компоненты будут передавать действия, такие как new-message вверх, чтобы можно было сохранить любые необходимые изменения состояния. Сделав еще один шаг вперед, коммуникационная сеть может быть упрощена путем подписки на все действия/события из дочерних компонентов, связанных с сообщениями. Таким образом, компонент обмена сообщениями становится координатором. Все дочерние компоненты обмена сообщениями взаимодействуют с ним через EventAggregator, но не взаимодействуют друг с другом.

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

Компонентно-ориентированная разработка — это будущее крупномасштабного клиентского JavaScript. Структурирование приложений таким образом дает ряд преимуществ. Однако важно выбрать явную стратегию управления изменениями состояния между этими компонентами. Если этого не сделать, вполне вероятно, что приложение станет необслуживаемым, поскольку границы между этими компонентами стираются. Это, во-первых, сведет на нет большинство преимуществ такого подхода. Data-Binding и EventAggregator можно комбинировать несколькими способами, чтобы реализовать явные шаблоны обмена сообщениями в приложениях Aurelia на основе компонентов.

Первоначально опубликовано на сайте sean-hunter.io 23 октября 2016 г.