Моя предыдущая публикация на Хабре достигла своих целей, — множество людей узнали о существовании W3View, некоторые посетили GitHub, кому-то наверное даже понравилось. В то-же время, последовавшие комментарии выявили потребность в более чётком описании того, какую задачу решает эта библиотека, как она это делает и для чего она может понадобиться вам (ну вдруг). Ежели, по какой-то причине, вам не интересно узнать, как можно строить развитый UI на Web технологиях не испытывая боли, тошноты и головокружения, — эта статья покажется вам скучной, осталных приглашаю под кат. По традиции, заведённой одним малым и innerHTML, UI в Web строится с помощью различных шаблонизаторов, за последние несколько лет шаблонизаторы прошли большой путь и развились до невозможности. Они должны были упростить создание интерфейсов, но задачи от этого проще не стали. Для решения сложных задач разработчики шаблоных движков ввели массу новых понятий и связали из косты изобрели разнообразные концепции. Некоторые концепции даже диктуют правила, по которым должна строиться Модель, что на мой взгляд совершенно противоречит здравому смыслу. Мы ведь пишем приложения не для концепций. При этом шаблонизатор не всегда избавляет нас от потребности использовать DOM API, как ни крути, а предусмотреть всё — невозможно. Однако прямое воздействи на DOM запросто может поломать любую, даже самую прекрасную концепцию…
Разработчики шаблонизаторов, дабы не допустить разрушения концепций, объявили такое воздействие анафемой и моветоном, — то есть, по нашему, анти-паттерном.  Ну и что остаётся делать разработчику, если то, что он разрабатывает не укладывается в шаблоны? — остаётся одно — искать альтернативу. Когда-то, давным-давно, HTML, Javascript и DOM API вполне позволяли обходиться без использования шаблонов и чёрной магии. HTML описывал структуру формы, Javascript, применяя DOM API, управлял этой формой и обрабатывал её события, это было красиво, просто и удобно. Но интерфейсы становятся всё сложнее и динамичнее, а HTML продолжает оставаться языком описания данных. Выходом может стать декомпозиция — разбиение большой и сложной формы на маленькие, независимые, переиспользуемые капсулы — компоненты. Декларация компонента может выглядеть как маленькая страничка HTML со скриптом, в котором описывается реакция на изменение данных и определяются обработчики событий. Потом из таких компонентов можно собирать более сложные. Как это устроено и как этим пользоваться я попробую объяснить на примере небольшого приложения. Долго думал о том какой пример лучше рассмотреть, остановился на W3View • TodoMVC. Готово, работает, сделано для демонстрации, есть с чем сравнивать, не слишком большое.  Со спецификацией, макетом и прочими входящими можно ознакомиться здесь. Наверное стоит взглянуть на спецификацию и макет прежде чем читать дальше. Я опущу описания Модели и Контроллера, они ничем не примечательны. Скажу лишь, что использовал классическую триаду MVC, где активная Модель реализует свою внутреннюю логику и не делает никаких предположений о том, как её будут отображать, Представление полностью базируется на W3View, а Контроллер связывает всё вместе в конечное приложение. Приложение реализует макет TodoMVC без изменений и не добавляет никаких своих стилей. Для упрощения, описание компонентов размещено в скрытом DIV, прямо на странице. Приложени подключается к странице четырьмя тегами SCRIPT: Первый — это библиотека W3View, второй и третий — Модель и Контроллер, четвёртый — скрипт запуска, главное в нём (из того, что имеет отношение к работе W3View), — это: Обычно я обхожусь меньшим количеством строк, но здесь решил для красоты почистить дерево DOM, что поделать — перфекционизм. При использовании предварительно подготовленного бандла, эти шесть строк превращаются в две: Понятное дело, бандл гораздо лучше для продакшена, но при разработке и для наглядности я предпочитаю подключать исходники. Подключили, инициализировали, запустили, а что? Да..., надо же было создать компоненты! Как я уже говорил, декларация компонента — это HTML элемент, поэтому достаточно просто распилить существующий макет на кусочки, описать реакцию на изменение данных и обработчики событий, а затем скомпоновать всё это обратно.  В TodoMVC несложно было выделить динамические части, и рутовый компонент APPLICATION получился такой: Как видите — просто HTML, с парой нестандартных атрибутов, двумя нестандартными тегами и неправильным типом тега SCRIPT.  Нестандартные теги MAIN и TOTALS, — это (как вы уже догадались) те самые динамические части, они выделены в отдельные компоненты и вставлены в APPLICATION как теги. Их мы рассмотрим позже. Итак SCRIPT. Мы должны указать Контроллеру о нашем Представлении, сделаем это при размещении приложения на странице, для этого определим в скрипте хэндлер onMount: Этот хэндлер вызывается сразу после вставки (монтирования) компонента в дерево DOM. Можно определить парный ему onUnmount, который вызывается непосредственно перед демонтированием компонента. Для того, чтобы они отрабатывали нужно монтаж и демонтаж производить специальными методами компонента — mount(targetElement, index) и unmount(). Если компонент демонтирован из DOM, его можно опять вмонтировать, при необходимости. Есть ещё onCreate и onDestroy, соответственно вызываются при создании и уничтожении компонента (уничтожать нужно методом destroy). При вызове destroy на экземпляре компонента, он сначала демонтируется (unmount()), а затем всё его поддерево тоже рекурсивно разрушается в хлам. После вызова destroy элемент уже нельзя использовать. Хэндлеры onCreate и onMount следует определять, если вам необходимо разместить ссылки на компонент в других объектах. Код, удаляющий эти ссылки, должен располагаться в хэндлерах onDestroy и onUnmount, это желательно делать симметрично. Просто нужно мыть руки, и тогда память не будет утекать. Так, с жизненным циклом разобрались, разберёмся теперь с изменением данных: Здесь всё просто — при получении новых данных раздаём их элементам в своём поддереве. Извне (здесь из Контроллера) данные устанавливаются методом setData, он уже присутствует во всех создаваемых экземплярах W3View компонентов и просто вызывает хэндлер onSetData, который нужно определить. Метод setData и хэндлер onSetData могут принимать до трёх аргументов: А в прочем, можно применять все три аргумента на своё усмотрение, передавайте туда всё, что посчитаете нужным, это зависит только от решаемой задачи и реализации хэндлера onSetData. this.ref.main и this.ref.totals — это ссылки на элементы в поддереве нашего компонента, помеченные атрибутом ref — ref="main" и ref="totals" соответственно, я об этом кажется уже упоминал.  В компоненте APPLICATION есть ещё один элемент, на нём стоит метка ref="newTodo", — это поле ввода. По спецификации в него можно вводить что-попало, но при нажатии на клавишу ENTER, это что-попало должно попасть в список тудушек. Естесственно, чтобы такое случилось, нужно обработать нажатие на ENTER. События в W3View обрабатываются совсем стандартным способом — навешиванием совсем стандартных обработчиков событий на обыкновенные элементы. В данном случае — onkeydown на элементе, на который мы поставили атрибут ref="newTodo". Всё совсем обыкновенно: взяли элемент, навесили событие, которое, если нажата клавиша ENTER, вызывает метод на Контроллере (Контроллер здесь называется appContext — помните, мы его передавали в new W3View — это он).  Готово, рутовый компонент приложения закончился, перейдём к следующему. Следующим будет MAIN, потому что компонент TOTALS тривиальный — не стану про него ничего писать. Просто такая-же установка атрибутов и свойств элементам DOM, ничего нового. А вот на компоненте MAIN стоит остановится поподробнее. Самое интересное в MAIN — использование встроенного ARRAY-ITERATOR: ARRAY-ITERATOR уже присутствует в каждом экземпляре W3View, этот компонент служит для вывода массивов. Он настраивается компонентом, который будет отображать элементы. В setData ARRAY-ITERATOR принимает два аргумента: Компонент, отображающий элемент массива получит три аргумента: Если вы укажете несколько компонентов для отображения элементов массива, то их экземпляры будут чередоваться, например: В таком случае — все нечётные элементы будут иметь класс "even", а все чётные — класс "odd". ARRAY-ITERATOR сделан на основе DIV, а здесь нам нужен UL, поэтому мы модифицируем его с помощью атрибута usetag="ul". Любой кмпонент W3View может получать такой атрибут для подмены тега, на основе которого он был объявлен. Если вам понадобится при объявлении компонентов использовать теги TBODY, TR или TD вне контекста TABLE, вы можете использовать атрибут tagname для любого элемента, кроме компонентов W3View. Ну вот, теперь вы всё знаете о том, как создавать компоненты, как их регистрировать в фабрике и как применять. Осталось только рассказать о способе удержать ваши компоненты в руках. TodoMVC — очень маленькое и простое приложение — всего четыре компонента понадобилось для описания его интерфейса, поэтому была возможность описать всё это прямо в странице. В реальной жизни компонентов может потребоваться очень много. Одних только кнопок, инпутов и прочих слайдеров случаются десятки, что уж говорить об экранчиках, панельках, формочках, всплывающих попупчиках и прочем всём остальном, за что так любят UI.  Конечно описывать всё это на странице не удобно, нужно выделять в отдельные файлы и желательно, чтобы это были не просто файлы, а модули с библиотеками компонентов. W3View позволяет загружать модули и разрешать зависимости между ними на лету. Для этого нужно использовать moduleLoader, использовать его нужно так: Это пример из папки loader пакета w3view. moduleLoader принимает четыре аргумента: Зависимости подключаются с помощью тега IMPORT, если к одной библиотеке нужно подключить другую, то в этой одной нужно написать: Имя, указанное в атрибуте as можно далее использовать в качестве неймспейса, примерно так: Таким образом становятся доступны все компоненты из подключаемой библиотеки. Сколько бы раз мы ни импортировали один модуль, он будет загружен только один раз, допускаются также рекурсивные зависимости. Для сокращения времени загрузки и разбора HTML описаний компонентов можно использовать билдер. Он находится в папке builder пакета w3view, там в файле build.js написано как им пользоваться. Результатом сборки является один js файл, включающий все импортированные библиотеки.  Вот собственно и всё, что следует знать о W3View, чтобы начать пользоваться. Сама библиотека гораздо меньше чем это описание, не составит большого труда разобраться в её устройстве просто заглянув в исходники, я старался сделать её как можно более простой и прозрачной. Библиотека не навязывает никаких правил, так что можно программировать так, как вы считаете нужным для решения ваших задач. Желаю удачи.