Что значит имя 2: Изучаем DurandalJS как SPA на примере сайта об именах

ru-RU | создано: 17.06.2014 | опубликовано: 17.06.2014 | обновлено: 01.01.2018 | просмотров за всё время: 7133

На этот раз будем знакомиться с DurandalJS, который является базовым фреймворком для нашего сайта, построенного по архитектуре Single Page Application. В статье будут описаны основные принципы и правила построения приложения на DurandalJS.

Оглядываясь назад

В прошлой статье был подготовлен проект для работы с DurandalJS создана первая (главная) страница, а в этой статье будем продолжать развитие проекта, пока не получится что-то наподобие нашего сайта примера. На данный момент при запуске проекта, некоторое время отображается  заставка (flash page), после чего появляется содержание первой страницы. Продолжим кодирование.

Разметка главной страницы (шаблона)

Так как наш главный модуль main.js запускает по умолчанию модуль-оболочку shell, который состоит из viewmodel и view (shell.js и shell.html). Shell.html - это, если так можно выразиться, "точка входа" для визального отображения. На мой взгляд, это самое оптимальное место для размещения шаблона сайта (дизайна разметки). Здесь и будем формировать основной вид сайта.

На данный момент она очень проста:

<section>
        <section id="content" class="container" data-bind="router: { transition: 'entrance', cacheViews: true }"></section>
</section>

Строка 2 имеет привязку к объекту router, Помните в прошлой статье мы описывали маршруты:

var routes = [
    { route: ['', 'home/index'], moduleId: 'site/home', title: 'Выбор буквы', nav: true },
    { route: 'about', moduleId: 'site/about', title: 'О проекте', nav: true }
];

Так вот, этот самый BindingHandler привязывает наши маршруты к разметке. Раз у нас есть маршруты, давайте выведем их список:

<section>
    <section id="content" class="container" data-bind="router: { transition: 'entrance', cacheViews: true }"></section>
    <ul data-bind="foreach: router.navigationModel">
        <li data-bind="css: { active: isActive }">
            <a data-bind="attr: { href: hash }, html: title"></a>
        </li>
    </ul>
</section>

В строке 3 я добавил привязку через foreach к навигационной модели (router.navigationModel) DurandalJS. Посмотрите что отобразилось на странице:

145-01

Хочется немного поэкспериментировать. Давайте создадим новый файл, я назову его footer.html и помещу его тут же, рядом с файлом home.html.

Содержание пусть будет пока :

<h1>Footer</h1>

Далее в shell.html поменяем разметку на такую:

<section>
    <section id="content" class="container" data-bind="router: { transition: 'entrance', cacheViews: true }"></section>
    <section data-bind="compose: 'site/footer.html'"></section>
</section>

Мне кажется, не трудно догадаться, что должно получится в конечном счете:

145-02

Именно то, что я и хотел. Теперь мой шаблон главной страницы состоит из двух файлов (представлений). А значит можно рендеринг маршрутов переносить в файл footer.html. После переноса при запуске сайта, я увидел ту же самую картинку как и на первом скриншоте.

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

Давайте теперь добавим немного стилей в разметку на основе правил bootstrap. У меня меню сайта получилось таким:

145-03

В моем меню два пункта, оба они указаны как маршруты в переменной routes:

var routes = [
    { route: ['', 'home/index'], moduleId: 'site/home', title: 'Выбор буквы', nav: true },
    { route: 'about', moduleId: 'site/about', title: 'О проекте', nav: true }
];

Обратите внимание, на параметр nav у каждого из маршрутов, если поставить значение в false, то этот маршрут не отобразится в меню. Вот как после манипуляций с footer.html и bootstrap выглядит содержание:

<div class="navbar navbar-default navbar-fixed-bottom" role="navigation">
    <div class="container">

        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
        </div>
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav" data-bind="foreach: router.navigationModel">
                <li data-bind="css: { active: isActive }">
                    <a data-bind="attr: { href: hash }, html: title"></a>
                </li>
            </ul>

            <ul class="nav navbar-nav navbar-right">
                <li><a href="http://www.calabonga.net">&copy;&nbsp;2014 Calabonga SOFT</a></li>
            </ul>
            <div class="pull-right" data-bind="css: { active: router.isNavigating }">
                <div class="progress progress-striped active page-progress-bar" data-bind="visible: router.isNavigating">
                    <div class="progress-bar" role="progressbar" style="width:150px;"></div>
                </div>
            </div>
        </div>
    </div>
</div>

Выделена 22 срока не случайно. В этой разметке осуществляется привязка свойство isNavigating у объекта router чтобы в момент смены активного маршрута на новый показывался индикатор загрузки, в моем случае, отображается progessBar из набора компонентов bootstrap.Пример работы переключения можно посмотреть на сайте примера.

Страница “О проекте”

В списке маршрутов у меня прописан путь на страницу “о проекте”, но пока такого модуля и представления не существует. Создадим его. Для этого в папке /views/site/ создаю представление модуля about.html:

<div class="btn-toolbar margin20">

    <div class="btn-group">

        <a href="#" class="btn btn-default" title="выбрать букву"><i class="fa fa-home fa-3x"></i></a>

    </div>

</div>

<div data-bind="blockUI: indicator">

    <h2 data-bind="text: title"></h2>

    <p>

        Проект "Что значит имя" содержит описание 718 имен. Выберите букву, найдите имя

        и выбрав его ознакомьтесь с характеристиками. На странице описания имени можно нажать на каждую букву и

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

    </p>

    <h2>Сайт создан из</h2>

    <p>

        При создании проекта "Что значит имя" были использованы следующие технологии и фреймворки:

        <ul>

            <li><a href="http://www.asp.net">ASP.NET MVC 5</a></li>

            <li><a href="http://durandaljs.com">Dudandaljs</a></li>

            <li><a href="http://www.breezejs.com/">BreezeJs</a></li>

            <li>EntityFramework</li>

            <li>FontAwesome</li>

            <li><a href="http://www.knockoutjs.com">Knockoutjs</a></li>

            <li><a href="http://jquery.com/">jQuery</a></li>

            <li><a href="http://requirejs.org/">RequireJS</a></li>

            <li>Microsoft.AspNet.Identity</li>

            <li>Microsoft.Owin</li>

            <li>Newtonsoft.Json</li>

            <li><a href="http://www.asp.net/vnext/overview/authentication">Asp.NET OWIN</a></li>

        </ul>

    </p>

    <h2>Как создать сайт</h2>

    <p>

        О поэтапных шагах по созданию сайта можно ознакомиться в <a href="http://www.calabonga.net">блоге автора</a>.

        Там же можно оставить комментарии и обратиться с вопросом через форму обратной связи.

    </p>

</div>

А вот содержание файла about.js:

define(function () {
    var
        title = 'О проекте';

    return {
        title: title
    };
});

Вот так выглядит страница “о проекте”

145-04

Заключение

В качестве заключения к этой статье, хочу рассказать о дальнейших планах. Следующим этапом, самое интересное на мой взгляд, работа с данными, вернее с базой данных посредствам Web API. Не просто Web API, а через BreezeJS. Хотя это уже не совсем связано с DurandalJS, потому что DurandalJS это всего лишь инструмент для достижения цели. А цель у нас сделать сайт с толкованием имен.

Ну, и ссылка на проект Github