Когда читаешь документацию какого-либо фреймворка, то пытаешься в голове составить какую-нибудь схему, которая бы описывала полный цикл создания приложения на нем. Однако, почему-то довольно часто найти описание такого процесса в документации не удается. Тогда приходится налегать на поисковик в надежде, что кто-нибудь добрый хотя бы чем-нибудь да намекнет на местонахождение описание устоявшихся паттернов.
По Ember.JS я нашел замечательную статью Extending TodoMVC With Ember CLI: Lists of Todo Lists (если ссылка не доступна, то ниже есть архив той статьи). Спасибо, John Mosesman, за Ваш труд! Такая хорошая ссылка не должна была потеряться где-то в пучинах EverNote, и я подумал, что необходимо поделиться с миром через блог. Формат, правда, был не ясен. Не могу же я одну ссылку запостить. Сначала мелькнула мысль сделать перевод. Но я не видел от него какого-то толку. Ведь наш брат итак неплохо должен знать английский. И тогда я решил поделиться своими комментариями по статье, так как они могут оказаться полезными.
Для лучшего понимания того, как приложение работает, я накидал схемку того, что происходит в Ember при открытие какого-либо URI. Хорошо бы перейти к чтению статьи Джона именно после разбора схемы.
Давайте разберем схему.
Первым делом URI и данные, которые передает пользователь через браузер попадают в Маршрутизатор (Router).
Router преобразует полученный URI в серию вложенных шаблонов. Тоесть у нас есть четкая связь какой путь в URI к какому набору шаблонов на выходе приведет. Под словом “шаблоны” на самом деле здесь подразумевается больше различных понятий: сами шаблоны (templates), компоненты (components), представления (views) и партиалы (partials). Но сейчас мы не будем вдаваться в различия между ними. Нам важно понять все в общих чертах.
На основе полученных данных мы также будем иметь информацию о том, какой маршрут (Route) использовать.
И далее по схеме у нас именно Route. Он не один на всё приложение как Router, а свой для определенного пути в строке браузера. Его задачи очень обширны, как я понял. И в процессе углубления знаний по Ember понимание круга его задач будет расти. Но в данный момент опять придется сузить рамки.
Route обрабатывает входящие данные (например параметры URI) и определяет какую модель загрузить. В зависимости от входящих данных он так же проделывает операции с объектом модели (изменение, добавление или удаление). Так же большая часть сообщества Ember считает, что обработчики событий (действий пользователя) так же должны быть в соответствующем Route. Однако часто я так же видел, что обработчики располагаются в контроллерах. В примере от John Mosesman, обработчики в роутах.
В общем, если мы будем говорить терминами таких backend-фреймворков как Ruby On Rails и Kohana, то route в Ember.Js выполняет практически те же функции, что контроллер в backend-фреймворках.
После прохождения маршрута (route) у нас есть экземпляр модели (или даже их коллекция) и серия вложенных шаблонов (которую мы получили еще в маршрутизаторе (router).
Далее по цепочке у нас идет контроллер. Если у нас роут уже выполняет функцию контроллера, то к чему еще контроллер? Оказывается он выполняет функцию декоратора, если говорить в терминах Ruby On Rails. Видимо создатели Ember хотели всячески усложнить вхождение новичков поэтому здесь такая путаница.
Декораторы RoR управляют отображением отдельных блоков в пределах одного шаблона. Например показом или скрытием определенных элементов управления в зависимости от ситуации.
Если роуты у нас фактически управляют моделями, то контроллеры Ember (как декораторы Ruby On Rails) управляют внешним видом отображения модели в шаблоне. Тоесть говорят шаблону как именно отобразить модель.
И вот у нас есть модель, шаблоны и корректировки отображения моделей в шаблонах (которые внес контроллер). После этого пользователь получает результат в своем браузере по запросу, который он вводил. Пользователю отображается страница с учетом переданного URI, параметров и всех действий, что пользователь производил в браузере.
Конечно при, практически, любых действиях пользователя у нас меняется URI в строке URL браузера. Тоесть роутинг выполняет свою главную функцию как и в Angular.
Описанные выше вещи важны для того, чтобы понимать как писать одностраничное приложение с Ember.JS. Зная где место каждого класса легче понять как заставить все эти классы работать сообща.
Так же будет полезным перед чтение этой статьи ознакомиться с todomvc. Здесь можно найти разбор кода реализации todomvc на Ember.
После этого можно перейти к статье Джона. Далее я вставлю еще несколько комментариев они будут кстати при чтении статьи. В статье буду встречаться термины и названия софта и ниже я поясню что это такое.
npm (node package manager) — это стандартный менеджер пакетов, автоматически устанавливающийся вместе с Node.js. Он используется для загрузки пакетов из облачного сервера npm, либо для загрузки пакетов на эти серверы. Как видно по статье, с помощью npm устанавливается ряд используемых пакетов. Пакетом в Node.js называется один или несколько JavaScript-файлов, представляющих собой какую-то библиотеку или инструмент.
bower – менеджер пакетов для клиентского JavaScript. Не стандартный, но самый популярный: сейчас там больше 11 тысяч пакетов. Надоело ходить на сайты JavaScript-библиотек и качать архивы каждый раз, как надо добавить на сайт очередной jQuery-плагин? Бовер сделает все сам. Менеджеры пакетов упрощают установку и обновление зависимостей проекта, то есть сторонних библиотек, которые он использует. У многих языков программирования есть стандартные менеджеры пакетов, которыми разработчики пользуются для установки всех библиотек: gem у ruby, pip у питона и так далее. У серверного Javascript есть npm, а у клиентского до недавнего времени ничего не было. Было множество разных пакетных менеджеров (Jam, Component, Volo, Ender), но большинство из них так и не стали популярными, а от менеджера пакетов, которым не поставишь нужных библиотек, толку мало.
Outlet. В шаблонах приложения имеются выражения в фигурных скобках. Они служат для того, чтобы брать информацию из модели и подставлять в шаблон. Среди таких выражений в статье можно встретить {{outlet}}. Этот помощник (helper) служит для отображения других шаблонов внутри текущего, которые меняются, когда пользователь перемещается внутри приложения.
Действие (action) – то, что происходит при определенных событиях (нажатию на элемент, отправке формы). Их обработчики описываются в контроллерах, маршрутах, представлениях, компонентах.
Action bubbling – это передача события вверх по цепочке если не был найден обработчик. Например, если в текущем контроллере не найден обработчик, то событие передается в текущий маршрут и производится поиск обработчика в нем.
Модели – это сущности, например в блоге – пост, пользователь, комментарий. Для создания объекта модели требуется получить данные. И тут есть 3 варианта:
- Получить их с помощью обращений к серверу через его API.
- Получить из локального хранилища.
- Создать фикстуры (скорее вариант для тестирования)
При работе с хранилищем все просто – данные там лежат уже в виде объектов и при запросе достаются оттуда, а вот для работы с API используются еще 2 сущности: адаптеры и сериализаторы.
Адаптеры задают правила работы с API, например получить все посты – GET /posts, а обновить пост – PUT /posts/1.
Сериализаторы разбирают json-ответ сервера и устанавливают формат json-запроса.
К счастью у Ember есть дефолтные готовые классы, которые подойдут во многих случаях. При желании можно создать их потомков и кастомизировать.
Вот, пожалуй, и все, что хотелось сказать в дополнение к статье.
Напоследок прикреплю архив статьи на случай, если она будет не доступна на сервере хозяина. И архив кода.