Сервер на Node.js - Шаблонизация (часть третья)

Сервер на Node.js - Шаблонизация (часть третья)

Содержание курса

  1. Начало
  2. Шаблонизация (часть первая)
  3. Шаблонизация (часть вторая)
  4. Шаблонизация (часть третья)

 

Теперь, когда мы с вами уже ознакомились с основами handlebars, давайте реализуем динамическое формирование страниц на нашем сервере.

 

Разбиение сервера

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

В корне проекта создаём 2 новых файла: other_functions.js и get_functions.js


 

Выносим нашу функцию поиска по массиву:

other_functions.js

// Функция поиска в массиве
function find(array, value) {
  for (var i = 0; i < array.length; i++) {
    if (array[i].url == value) return i;
  }
  return -1;
}


// Открываем ф-ию для вызова из других файлов
exports.find = find;

Здесь будут храниться все наши маленькие функции, для которых слишком много отдельного файла.

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

// Библиотеки
var other_functions = require("./other_functions");

И обращаемся к нашей функции:

other_functions.find(bd , pathname);

 

Теперь вынесем в отдельный файл часть кода, отвечающую за обработку запроса:

get_functions.js

// Библиотеки
var other_functions = require("./other_functions");


// Функция формирования и отправки страницы
function page_send(req, res, pathname, bd) {
  // Проверяем url
  var result = other_functions.find(bd , pathname);
  if(result != -1) {
    res.render(bd[result].file);         // Если страница найдена, то отправить соответствующий файл на клиент
  } else {
    res.status(404).render('404.hbs');   // Иначе, отправить ошибку 404
  }
}


// Открываем ф-ию для вызова из других файлов
exports.page_send = page_send;

В самом начале мы подключаем нашу библиотеку с ф-ей поиска. Далее идёт уже знакомый нам код, только обёрнутый в ф-ю page_send(), чтобы к нему можно было обращаться из вне.

 

Теперь файл server.js выглядит следующим образом:

// Библиотеки
var get_functions = require("./get_functions");

// Подключаемые модули
var express = require('express');
var url = require("url");
var hbs = require("hbs");


var app = express();  // Привязываем express к нашему "приложению"
app.use(express.static(__dirname + '/public')); // Теперь мы сможем обращаться из браузера к любым файлам в этой папке


// Для шаблонов страниц
hbs.registerPartials(__dirname + "/views/templates", function() {
  app.set("view engine", "hbs");


  // Блок переменных
  var pathname = '';  // Переменная для хранения текущего url

  // База данных
  var bd = [
    {url: '/', file: 'index.hbs'},
    {url: '/about', file: 'about.hbs'},
    {url: '/contacts', file: 'contacts.hbs'},
    {url: '/post-1.html', file: 'post_1.hbs'},
    {url: '/post-2.html', file: 'post_2.hbs'}
  ];


  // Обработчик запросов
  app.use(function(req, res, next) {
    // Определяем текущий url
    pathname = url.parse(req.url).pathname;

    // Вызываем ф-ю формирования и отправки страницы
    get_functions.page_send(req, res, pathname, bd);
  });


  app.listen(3000);   // Установка порта
});

Всё чисто и понятно - осталась лишь общая логика, а все рутинные процессы вынесены в отдельный файл.

 

Расширение БД

server.js

// Библиотеки
var get_functions = require("./get_functions");

// Подключаемые модули
var express = require('express');
var url = require("url");
var hbs = require("hbs");


var app = express();  // Привязываем express к нашему "приложению"
app.use(express.static(__dirname + '/public')); // Теперь мы сможем обращаться из браузера к любым файлам в этой папке


// Для шаблонов страниц
hbs.registerPartials(__dirname + "/views/templates", function() {
  app.set("view engine", "hbs");


  // Блок переменных
  var pathname = '';  // Переменная для хранения текущего url

  // БД доступных страниц
  var bd_url = [
    {url: '/', file: 'index.hbs', type: 'main'},
    {url: '/about', file: 'about.hbs', type: 'information'},
    {url: '/contacts', file: 'contacts.hbs', type: 'information'},
    {url: '/post-1.html', file: 'post.hbs', type: 'post'},
    {url: '/post-2.html', file: 'post.hbs', type: 'post'},
    {url: '/post-3.html', file: 'post.hbs', type: 'post'},
    {url: '/post-4.html', file: 'post.hbs', type: 'post'},
    {url: '/post-5.html', file: 'post.hbs', type: 'post'}
  ];

  // БД статей
  var bd_posts = [
    {url: '/post-1.html', title: 'Статья №1', category: 'Новая рубрика', author: 'Admin', date: '07.08.2017', description: 'Описание 1', text: 'текст статьи'},
    {url: '/post-2.html', title: 'Статья №2', category: 'Новая рубрика 2', author: 'Admin', date: '08.08.2017', description: 'Описание 2', text: 'текст статьи'},
    {url: '/post-3.html', title: 'Статья №3', category: 'Новая рубрика 2', author: 'Admin', date: '08.08.2017', description: 'Описание 3', text: 'текст статьи'},
    {url: '/post-4.html', title: 'Статья №4', category: 'Новая рубрика 2', author: 'Admin', date: '08.08.2017', description: 'Описание 4', text: 'текст статьи'},
    {url: '/post-5.html', title: 'Статья №5', category: 'Новая рубрика 2', author: 'Ванька', date: '08.08.2017', description: 'Ничего нового', text: '<b>Обычный</b> текст'}
  ];

  // БД комментариев
  var bd_comments = [
    {url: '/post-1.html', author: 'Иван', date: '03.08.2017', text: 'КеК ЛоЛ АрбидоЛ'},
    {url: '/post-1.html', author: 'Ванька', date: '04.08.2017', text: 'Очень полезная статья!'},
    {url: '/post-2.html', author: 'Вано', date: '07.08.2017', text: 'Вот это прикол!'}
  ];


  // Обработчик запросов
  app.use(function(req, res, next) {
    // Определяем текущий url
    pathname = url.parse(req.url).pathname;

    // Вызываем ф-ю формирования и отправки страницы
    get_functions.page_send(req, res, pathname, bd_url, bd_posts, bd_comments);
  });


  app.listen(3000);   // Установка порта
});

Мы добавили дополнительное поле в БД доступных страниц - type. Пока у нас будет 3 основных типа main - главная страница, на которой будут отображаться превью наших статей, post - страницы самих статей, и information - статические информативные статьи, к которым мы ничего подгружать не будем.

Кроме этого мы добавили две новых БД - БД статей и БД комментариев.  В них будет храниться вся уникальная информация для каждой статьи и коммента. Конечно же меняется и список параметров функции page_send()

get_functions.page_send(req, res, pathname, bd_url, bd_posts, bd_comments);

 

Формирование данных для шаблона

Теперь давайте напишем функционал, формирующий необходимые данные и отправляющий их на клиент. 

И так, теперь редактируем файл get_functions.js

// Библиотеки
var other_functions = require("./other_functions");


// Функция формирования и отправки страницы
function page_send(req, res, pathname, bd_url, bd_posts, bd_comments) {
  // Определяем индекс запрашиваемой страницы в БД доступных страниц
  var page_index = other_functions.find(bd_url, pathname);

  if(page_index === -1) {                                       // Если страницы в БД нет, то отправить ошибку 404
    res.status(404).render('404.hbs');
  } else {
    if(bd_url[page_index].type === 'information') {             // Если запрашиваемая страница - информационная, то отправить нужный файл
      res.render(bd_url[page_index].file);
    } else {
      if(bd_url[page_index].type === 'main') {                  // Если запрашиваемая страница - главная, то:

        // Создать массив для хранения информации о статьях
        var posts = [];

        // Заполнить массив
        for(var i = 0; i < bd_posts.length; i++) {
          posts.push({
            url: bd_posts[i].url,
            title: bd_posts[i].title,
            category: bd_posts[i].category,
            author: bd_posts[i].author,
            date: bd_posts[i].date,
            description: bd_posts[i].description
          });
        }

        // Вернуть файл и необходимые данные
        res.render(bd_url[page_index].file, {
          posts: posts
        });
      }
    }
  }
}


// Открываем ф-ию для вызова из других файлов
exports.page_send = page_send;

Если запрашиваемой страницы нет в БД, то просто возвращаем файл 404.

Если страница информативная (т.е. подключать ничего не надо), то тоже просто возвращаем соответствующий файл.

А вот если запрашиваемая страница - главная, то:

  • создаём массив для хранения превью
  • планомерно заполняем его необходимыми данными
  • отправляем сформированный массив на клиент

 

Вставка данных в шаблон

Пол дела сделано! Но нужно ещё правильно принять эти данные и обработать их - меняем файл index.hbs

<!DOCTYPE html>
<html>
	<head>
		<title>Какой-то сайт.ru</title>
		<meta charset="utf-8">
    <link rel="stylesheet" href="/style.css">
	</head>

	<body>
		{{> header}}

		<div id = "box">
			<div id = "content">
				{{#each posts}}
					<div id = "post">
						<div id="meta">
							<span><a href="{{url}}#comments" title="Комментарии"><img src="/img/comments.png"> <b>0</b></a></span>
							<span><a href="{{url}}" title="Рубрика"><img src="/img/category.png"> <b>{{category}}</b></a></span>
							<span><a href="{{url}}" title="Автор"><img src="/img/author.png"> <b>{{author}}</b></a></span>
							<span><a href="{{url}}" title="Дата создания статьи"><img src="/img/calendar.png"> <b>{{date}}</b></a></span>
						</div>

						<a href="{{url}}"><img src="img/about.png" alt="{{title}}"></a>
						<a href="{{url}}"><h2>{{title}}</h2></a>

						<p>{{description}}...</p>

						<br>

						<a href="{{url}}" class="button">Читать далее >></a>
					</div>
				{{/each}}
			</div>

			{{> sidebar}}

			<div id = "clear"></div>
		</div>

		{{> footer}}
	</body>
</html>

Вот тут в дело и вступает hbs. Мы перебираем полученный массив (аналог for) и вставляем данные на страницу.

Теперь, если вы измените БД статей, то и главная страница сразу же изменится (обратите внимание, что новую статью необходимо прописывать и в БД доступных страниц и в БД статей).

Попробуйте дописать функционал для обработки страниц статей. Если возникнут проблемы - смотрите исходники или задавайте вопросы в комментах.

TEXT.RU - 100.00%

Поделиться ссылкой:

Добавить комментарий

Зарегистрируйтесь или Войдите, чтобы оставить комментарий.

Системное сообщение