-
Notifications
You must be signed in to change notification settings - Fork 1
Main Logic Deep
Рассмотрим подробно всю цепочку событий с момента загрузки. Все модули пишутся в формате AMD и имеют, соответственно, прописанные взаимные зависимости.(…ссылку… на карту зависимостией)
- Initialization
- onClicks binding
- Section loading and changing
- Transitioning and Invoking
- Widgets initializing
- Finish steps
- Bonus track: History
app — точка входа. Подключается на странице сайта.
Инициализирует все приложение на основание файла config
В конфиге задаются кастомные имена html-атрибутов, задается приоритет временных хранилищ, а также могут указываться опциональные модули для подключения (сейчас таких нет). Также при инициализации подключается обработчик ошибок с возможным логированием.
На последнем шаге подгружаются модули sections, loader и clicks.
events генерится событие pageTransition:init, а само оригинальное событие (click) отменяется (evt.preventDefault()).
На `pageTransition:init` подписан модуль `sections`, который содержит в себе общий менеджер переходов между страницами (transitions). Его работа основона на модулях [`sections/transition`](../blob/master/app/client/sections/transition.coffee), [`sections/loader`](../blob/master/app/client/sections/loader.coffee) и [`sections/cache`](../blob/master/app/client/sections/cache.coffee).
Происходит проверка, есть ли у нас в кэше уже нужная запись с url, и если есть, то просто создается новый объект перехода (transition) на базе соответствующей информации из кэша.
Если в кэше нет подходящих данных, то вызывается sections/loader, который призван подгрузить секции с сервера. После подгрузки он генерит событие sections:loaded с данными о загруженных секциях. В реакции на это событие текущий модуль sections создает новый объект перехода на основании этих загруженных данных.
На вход модуль конструктор получает данные о новых секциях, которые надо вставить, пропускает их через парсер sections/parser и отдает модулю sections/invoker, который и осуществляет непосредственную замену секций в DOM.
Invoker на основании данных про новые секции строит пары отдельных объектов типа Section (sections/section). Один элемент в паре — секция, которую надо вставить в конкретное место в DOM. Второй элемент — секция, которая заменится этой вставкой (вынется из DOM).
Каждая секция сама себя вставляет или вынимает, генеря при этом событие section:inserted или sections:removed, соответственно. Если секция была объявлена в рамках какого-то пространства имен, например, popup, то будут созданы дополнительные события вроде section-popup:inserted. К каждому такому событию приложены данные о конкретной секции.
Invoker после окончания замены всех секций также генерит общее событие sections:inserted.
Также Invoker следит за тем, чтобы секции не забыли включить все свои виджеты при вставки и выключить при удалении.
Таким образом все пользовательские скрипты знают в рамках какого html-блока они работают. На базе одного и того же js-файла виджета может быть создано несколько виджетов, если такие указания есть у разных узлов. Все эти виджеты будут обладать своим DOM-контекстом.
Напомним, что Invoker выключает связанные виджеты при вынимании секций со страницы (связанные виджеты — все, которые есть внутри DOM этой секции), и включает их при возвращении этой секции обратно на страницу. (back/forward из браузерной навигации).
… здесь чуть позже будет про нюансы с кэшированием ... `window.history` в расширенном внутреннем варианте [`history`](../blob/master/app/client/history.coffee) проходит полосой сквозь многие модули. Бессмысленно говорить о подгрузке секций на лету, если мы не можем делать `pushState`. Поэтому `clicks`, `sections/loader` и другие даже не инициализируются, если в браузере недоступен window.history.Тем не менее Widgets initializing нам все равно необходим, так как нужно связать написанные пользователем скрипты и DOM-узлы для корректной работы этих скриптов.