Блог начинающего фронтендера

Погружение в Marionette.js. Часть 1

Для нашего приложения мы будем использовать Bootstrap и Marionette со всеми зависимостями

Организация проекта

  • project folder
    • index.html
    • assets
      • css
      • img
      • js
        • vendor

Зависимости

В папку assets/js/vendor положим все зависимости:

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

Скачаем файлы Bootstrap и положим css и img файлы в соответствующие папки:

  • css/bootstrap.css -> assets/css/bootstrap.css
  • img -> assets/img

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

Так же создадим свой файл стилей application.css.

Отображение статического контента

После того как мы подготовили проект можно начать с отображением контента с помощью Marionette в нашем index.html

В начале мы вставим наш JS код в HTML файле. Это не лучшая практика, как только вы начнете делать что-то сложнее обычной записной книжки вы просто сойдете с ума. Позже мы сделаем рефакторинг кода

Добавим JS код в нижнюю часть index.html

var ContactManager = new Marionette.Application(); //объявляем наше приложение 
ContactManager.start(); //запускаем наше приложение

Мы объявили наше Marionette приложение и запустили его.

var ContactManager = new Marionette.Application();
ContactManager.on("start", function(){
    console.log("ContactManager has started!"); //выводим сообщение в консоль после того как приложение запустилось
});
ContactManager.start(); //обратите внимание, что мы определили обработчки start до запуска приложения

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

  • Нам нужно иметь представление для отображения
  • Нам нужно иметь шаблон в котором будет отображаться наше представление. Таким образом приложение будет знать что и как отображать
  • Нам нужно иметь область на нашей странице, куда Marionette можем вставить представление для отображения

Вот как выглядит наш index.html после этого:

Затем, после библиотек, которые мы подключили:

Мы добавили тот функционал, который обсуждался выше и необходим для отображения нашего представления:

  • Мы определили главную область "main-region", в которой будем отображать наше представление (строки 2-4)
  • Мы определили шаблон для нашего представления (строки 6-8)
  • Мы определяем представление для отображенния
    • DOM элемент в котором будут отображено представление (1)
    • шаблон для использования (2)

Все что осталось сделать - это создать новый экземпляр представления (3) и запустить его (4)

Сейчас наше приложение выглядит так:

Вместо того, чтобы объявлять глобальные переменные для хранения, например, объявление нашего преставления (загрязняя таким образом глобальное пространство имен), мы объявляем их в нашем приложении (как атрибуты ContactManager.StaticView).

Важные момент: Marionette, как и Backbone в целом, нуждается в шаблоне для отображения представления:

  • Шаблоны:
    • это обычный HTML
    • определяет "как данные должны отображаться" (какой HTML должен быть в представлении, CSS стили, где данные должны отображаться)
  • Представление:
    • JS объекты
    • заботится о том, как "реагировать на вещи, которые случаются" (клики, отслеживание моделей и тд)

Может возникнуть путаница если вы раннее использовали MVС веб-фреймворки. В них шаблон и представление объединены в "представлении" (view) как части MVC: они получают данные из экземпляров модели предоставленных контролером, затем генерируют HTML, который отправляется браузеру. Как только такой HTML будет отображен фреймворком, он никогда не изменится: новое представление может быть создано тем же контролером (например, on refresh), но этот конкретный экземпляр никогда не изменяется.

В приложениях Marionette представление загружается и пользователь обычно взаимодействует с ним нажимая на кнопки или изменяя данные. Так как мы не обновляем страницу какждый раз, когда пользователь взаимодействует со странице, нам нужно управлять пользовательскими действиями внутри представления. Если пользователь изменяет какие-то данные, представление отображающее эти данные должно обновляться мгновенно, при этом не будет взаимодействия с сервером или обновления страницы. Например, если пользователь изменяет номер телефона контакта внутри всплывающего окна, все представления отображающие этот контакт должны обновиться когда данные будут сохранены. Но как мы можем обновить данные без обращений к серверу и как поймем, что информация обновлена? Это обязанность представления в Marionette: оно следит за моделями, которые показывает и если эти модели изменяются, то представление обновляет себя самостоятельно используя тот же шаблон. И, чтобы соответствовать шаблону "разделения ответственности", функционал "представления" был разделен на "шаблоны" (как отображть информацию) и "представление" (как реагировать на изменения в среде).

В Marionette модели и представления объявляются как JS объекты, содержащие свойства ключ-значение. В JS var myModel = { muAttribut: "myValue" } объявляет валидный объект, а myModel.myAttribute вернет "myValue".

Наш шаблон определен внутри тега script с типом text/template. Это небольшой трюк для обмана браузера:

  • это не HTML, поэтому браузер не будет пытаться его отобразить
  • это не JS, поэтому браузер не будет пытаться его выполнить

При этом мы можем легко добавить атрибут id этому тегу script, что позволяет нам выбрать его с помощью jQuery. Это происходит в строке (4), где мы выделяем какой шаблон использовать присваивая нашему представлению jQuery селектор. Все остальное за нас делает Marionette.

Что насчет объявления el перед этим? Marionette нужно будет где-то на нашей странице отобразить представление, поэтому мы просто присваиваем jQuery селетор DOM элементу, который будет содержать наше представление, добавляем id элемент в строке (1). Позже мы увидим более удобные варианты управления нашими представлениями в Marionette, особенно для намного более сложного интерфейса.

Теперь вместо того, чтобы показывать простое сообщение в консоли, мы ссылаемся на новое представление когда наше приложение запускается и показываем его внутри предопредленного DOM элемента.

Текущий внешний вид нашего приложения

Динамическое изменение статического представления

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

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

Мы создали новый шаблон для отображение нового текста. Далее нам нужно предоставить другой шаблон для нашего представления во время отображения:

var staticView = new ContactManager.StaticView({
    template: "#different-static-template"
});

Теперь в главной области будет отображаться новый текст.

Текущий внешний вид нашего приложения.

Определяем другие атрибуты представления

Давайте посмотрим как можно обеспечить другие опции, которые переданы в наше представление, что позволяет нам определить HTML теги, которые используются для отображения нашего представления, добавить id и class.

Если посмотреть на исходный код (с помощью developer tool), то видно, что Marionette отобразился внутри div тега.

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

ContactManager.StaticView = Marionette.ItemView.extend({
    id: "static-view",
    tagName: "span",
    className: "instruction",
    template: "#static-template"
});

Такое определение сгенерирует следующией HTMLкогда будет отображено:

Чтобы узнать больше об опция представления, можно ознакомиться с документацией backbone по Конструктору представления. Эти опции могут быть объявлены когда представление объявлено:

var staticView = new ContactManager.StaticView({
    id: "static-view",
    tagName: "span",
    className: "instruction"
});

Внедряем управление областями

Использование render для отображения представления внутри специфичного DOM элемента работае отлично. По сути так Backbone приложения отображают свое представление. Однако, так как нам бы хотелось двигаться дальше и написать более сложное приложение, будет намного проще для нас если Marionette сможет взять на себя отображение и удаление представлений. Для достижения этого мы будем использовать "супер представление" на уровне нашего приложения: оно будет содержать различные области, и мы в дальнейшем будем отображать наши представления внутри этих областией.

Мы будем использовать LayoutView от Marionette. Его мы коснемся глубже немного позже. Вот как оно объявляется:

var RegionContainer = Marionette.LayoutView.extend({ //в поздних версиях заменен на View
    el: "#app-container",
        regions: {
        main: "#main-region"
    }
});

Вот релевантный фрагмент index.html:

Мы заявляем, что наш RegionContainer должен показать себя в элементе "app-container" в области "main-region". Как вы заметили, мы снова использовали jQuery DOM селектор чтобы выделить какой DOM элемент мы хотим использовать.

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

Текущий внешний вид нашего приложения.

До того как наше приложение запустится мы подтверждаем область для хранения нашего представления (1) и присваиваем ее к ContactManager.regions для быстрого доступа. Затем мы просто показываем наше представление внутри области main (2): области, которые мы объявили в нашем представлении автоматически доступны через ContactManager.regions. Если пока это недостаточно понятно, не беспокойтесь, мы позже охватим использование макетов представлений.

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

Поделиться
Отправить
Отправить