Хочу, чтобы в адресной строке, отображалось название контента, который на данный момент отображается на странице. Прочитал кучу всего, но увы, node js мне пока не подается...
На данный момент у меня Server выглядит так:
var express = require('express'),
bodyParser = require('body-parser'),
http = require('http'),
path = require('path'),
fs = require('fs'),
id3 = require('id3js'),
router = require('routes'),
webSocketServer = require('ws').Server,
wss = new webSocketServer({ port: 8001 })
getFilesName = require('./myModule/getFilesName'),
mongoose = require('mongoose'),
async = require('async');
var app = express();
var server = http.createServer(app);
app.use(express.static(path.join(__dirname, '/public')));
app.use(bodyParser.json());
Это мой ajax: файл ajax.js
function ajax(url, callback, data, request) {
try {
request = new(this.XMLHttpRequest || ActiveXObject)('MSXML2.XMLHTTP.3.0');
request.open(data ? 'POST' : 'GET', url, 1);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.setRequestHeader('Content-type', 'application/json');
request.onreadystatechange = function () {
request.readyState > 3 && callback && callback(request.responseText, request);
};
request.send(data)
} catch (e) {
window.console && console.log(e);
}
};
И допустим есть пара кнопок, меню, и при нажатии на одну из кнопок я в подргужаю что-то на страницу, допустим это slider.
Вот так я подгружаю slider на страницу
файл main.js
document.getElementById('menuSlader').addEventListener('click', function() {
ajax('../pages/slider/index.html', function(res) {
document.getElementById('main').innerHTML = res;
})
})
И тут вопрос - как мне изменить состояние адресной строки и получить такой результат http://localhost:8008/slader, если на странице на данный момент отображается slader
Ответ
Главное что нужно помнить меняя URL - это общее правило: любой URL пользователь может скопировать и кому-нибудь передать. Поэтому если вы решили поменять URL - должна быть возможность этот URL открыть минуя главную страницу.
Для того чтобы избежать дублирования, в SPA-приложение вводится отдельный инфраструктурный компонент: роутер, который получает на вход адрес текущей страницы, а на выходе показывает нужные данные.
Тут выделяется два основных подхода: клиентская маршрутизация и изоморфная маршрутизация (работающая вместе с изоморфным рендером).
Клиентская маршрутизация (client side router)
Идея этого способа - все делаем только на клиенте, сервер даже не знает что URL поменялся. Тут все очень просто: маршрут записывается в поле хэша в URL (эта часть URL не передается на сервер). Ссылки на части SPA оформляются вот так, без всякого кода:
...
Если же нужно программное переключение на нужную страницу - это делается вот так:
location.hash = '/foo';
Далее подобные переходы нужно где-то обрабатывать. Для этого существует событие hashchange:
window.addEventListener('hashchange', function (e) {
var url = e.newURL;
navigate(url.substring(url.indexOf('#')+1));
});
navigate(location.hash); // Не забываем обработать открытие страницы тоже!
Осталось реализовать функцию navigate - она должна в зависимости от переданного ей маршрута загрузить с сервера нужные данные и отобразить их.
Изоморфная маршрутизация
Способ выше индексируется не всеми роботами, а также требует обязательного использования javascript, поэтому от него периодически пытаются отказаться. Вместо этого придумываются способы заставить сервер при необходимости отображать страницу точно так же как вы это делаете на клиенте.
Для этого можно попытаться заставить сервер и клиент исполнять строго один и тот же код - в таком случае то что получилось называется изоморфным рендером. Для изоморфного рендера обычно используют фреймворки которые его поддерживают: React, Vue, Angular.
Ну или можно скостылить что-нибудь вручную чтобы результат получался примерно одинаковым - тогда это будет изоморфная маршрутизация.
На клиенте переходы между страницами должны быть вот такими (иначе им нельзя будет воспользоваться с отключенным JS):
Разумеется, обрабатывать нажатия тут нужно по-особому:
document.addEventListener('click', function (e) {
for (var target = e.target; target; target = target.parentElement) {
if (target.tagName === 'A') {
break;
}
}
if (target && target.href[0] === '/') {
go(target.href);
e.preventDefault();
}
});
function go(url) { // также эту функцию можно использовать для программной смены текущей страницы
navigate(url);
history.pushState(null, document.title, url);
}
Также можно придумать аналогичный обработчик для события submit у форм - в таком случае формы ввода тоже смогут работать без javascript.
При использовании HistoryAPI нельзя забывать про обработку события popstate:
window.addEventListener("popstate", function (e) {
navigate(location.pathname);
});
Наконец, серверная часть. На сервере вам нужно выслать измененную страницу со всеми нужными данными. Например, с использованием cheerio:
const cheerio = require('cheerio');
app.get('/foo', function(req, res, next) {
fs.readFile(path.join(__dirname, '/public/index.html'), function(err, content) {
if (err) { next(err); return; }
var $ = cheerio.load(content);
// $('#main').html(...);
navigate($, '/foo', function (err) {
if (err) { next(err); return; }
res.send($.html());
});
});
});
Осталось реализовать функцию navigate два раза - на клиенте и на сервере.
Комментариев нет:
Отправить комментарий