Каждый достаточно сложный вебсайт имеет много повторяющихся элементов на своих страницах, например, верхняя часть сайта – заголовок (header) или нижняя – «подвал» (footer).
Структура этих элементов не изменяются с каждой новой страницей, могут меняться лишь данные. Например, на разных страницах ссылки навигационного меню могут различаться, однако структура его останется прежней.
В vibe.d имеется встроенный шаблонизатор Diet, который позволяет следовать принципу «Не повторяйся» (Don’t Repeat Yourself или DRY) за счет создания шаблонов с базовой структурой и включения их в шаблоны конкретных типов страниц.
Давайте создадим несложный шаблон главной страницы и на его примере разберем работу Diet. Если Вам удобнее и привычнее писать на html, то можно воспользоваться транслятором из html в jade-синтаксис. Изменим шаблон index.dt из прошлой статьи на следующий:
doctype html html head meta(charset='utf-8') | title Название сайта | link(rel='stylesheet', type='text/css', href='style.css') | body header | Заголовок сайта | nav ul li a(href='link1') Ссылка 1 | li a(href='link2') Ссылка 2 | li a(href='link3') Ссылка 3 | article h1 Название статьи | p Тут будет содержимое статьи, когда нибудь. | footer | "Подвал" сайта.
Компилируем и смотрим: На нашем сайте пока имеется лишь одна страница, но на ней уже есть основные элементы: header, content и footer. Кроме того, мы подключили файл стилей (style.css), но не создали его. Исправим ситуацию. Создадим файл style.css со следующим содержимым положим в папку public (в ней будут доступные всем статичные файлы):
body { font-size: 1em; color: black; background-color: white; font-family: Arial; } header { display: block; font-size: 200%; font-weight: bold; text-align: center; } footer { clear: both; display: block; text-align: center; } nav { display: block; float: left; width: 25%; } article { display: block; float: left; }
Также следует изменить код сервера на следующий:
import vibe.d; shared static this() { // создаем url-роутер и настраиваем его auto router = new URLRouter; router.get("/", staticTemplate!"index.dt"); router.get("*", serveStaticFiles("public/")); auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["127.0.0.1"]; // запускаем сервер с настройками и роутером listenHTTP(settings, router); logInfo("Please open http://127.0.0.1:8080 in your browser."); }
Компилируем, запускаем наш сайт и обновляем страничку. Если изменений нет, то обновите без кеша (Ctrl+F5). Теперь и стили работают.
Приступим же к разделению нашего шаблона на родительский и дочерний с целью удобства и отсутствия повторений. Создадим файл layout.dt, который будет определять общую структуру страницы, а index.dt наследует его и добавит новый контент.
Ключом к использованию наследования шаблонов является выражение block. Оно имеет имя и содержит некоторую часть шаблона, по сути, блок кода. Дочерний шаблон может переопределять block и выводить свой код или выводить код родительского шаблона. Сделаем в файле layout.dt четыре блока: header, nav, content и footer. Для всех блоков, кроме content, напишем содержимое. Блок контента обозначим, но будет он у нас пустым:
doctype html html head meta(charset='utf-8') title Название сайта link(rel='stylesheet', type='text/css', href='style.css') body block header header Заголовок сайта block navigation nav ul li Ссылка 1 li Ссылка 2 li Ссылка 3 block content block footer footer "Подвал" сайта.
Теперь изменим наш главный шаблон index.dt на следующий:
extends layout block content article h1 Название статьи p Тут будет содержимое статьи, когда нибудь.
В нем мы наследовались от шаблона layout и добавили содержимое для блока content. Снова компилируем, запускаем и обновляем вкладку в браузере. Ничего не изменилось, а значит все работает как надо!
Естественно, можно создавать сколько угодно блоков, лишь бы было удобно. Однако, наследование не является единственным способом избежать повторения кода шаблона. Ключевое слово include позволит вставить содержимое другого файла в текущий шаблон. Для примера, создадим отдельный шаблон для навигации вфайле nav.dt, следующим образом:
nav ul li Ссылка 1 li Ссылка 2 li Ссылка 3
Теперь сделаем включение этого шаблона в layuot.dt:
doctype html html head meta(charset='utf-8') title Название сайта link(rel='stylesheet', type='text/css', href='style.css') body block header header Заголовок сайта block navigation include nav block content block footer footer "Подвал" сайта.
На первый взгляд, между наследованием и включением никакой разницы. Но она есть: включение просто вставляет блок данных в шаблон, а наследование позволяет изменять данные «на лету». В будущих статьях мы разберем эту тему подробнее.