Представьте, что вы заходите на сайт, и он не перезагружается каждый раз, когда вы кликаете по ссылке. Всё работает плавно, как в настольной программе. Это и есть одностраничное приложение, или SPA. В этой статье я покажу, как написать такое приложение на чистом JavaScript без фреймворков. Вы удивитесь, но это проще, чем кажется.
Что такое SPA и зачем оно нужно?
SPA — это веб-приложение, которое загружается один раз, а потом обновляет только нужные части страницы. Пользователь не видит белых экранов и миганий. Всё происходит быстро и отзывчиво. Так работают Gmail, Trello, Notion.
Основные плюсы SPA:
- Быстрый отклик интерфейса
- Меньше трафика (не нужно каждый раз качать весь HTML)
- Похоже на мобильное приложение
- Легко кэшировать данные
Но есть и минусы: сложнее с SEO, нужно больше JavaScript, могут быть проблемы с историей браузера. Но этим управляют современные инструменты.
Как работает SPA изнутри
В классическом сайте каждый переход — это запрос к серверу. Сервер отдаёт новую HTML-страницу. В SPA сервер отдаёт только один HTML-файл, а дальше JavaScript управляет всем.
Основные компоненты SPA:
- Роутер — определяет, какой компонент показать в зависимости от URL
- Шаблонизатор — создаёт HTML на основе данных
- Состояние — хранит данные приложения (например, список задач)
- События — обрабатывают клики, ввод текста и т.д.
Когда пользователь кликает по ссылке, JavaScript меняет URL в адресной строке (без перезагрузки), подгружает данные и обновляет часть страницы. Всё это происходит в браузере.
Пишем простой роутер на JavaScript
Начнём с самого главного — роутера. Он будет смотреть на адресную строку и решать, что показывать. Вот пример:
class Router {
constructor() {
this.routes = {};
window.addEventListener('hashchange', () => this.resolve());
}
addRoute(path, handler) {
this.routes[path] = handler;
}
resolve() {
const hash = window.location.hash.slice(1) || '/';
const handler = this.routes[hash];
if (handler) {
handler();
} else {
this.routes['404']();
}
}
}
// Использование
const router = new Router();
router.addRoute('/', () => {
document.getElementById('app').innerHTML = 'Главная
';
});
router.addRoute('/about', () => {
document.getElementById('app').innerHTML = 'О нас
';
});
router.addRoute('404', () => {
document.getElementById('app').innerHTML = '404 — Страница не найдена
';
});
router.resolve();
Здесь мы используем хеши (#/about). Когда хеш меняется, срабатывает событие hashchange. Роутер находит нужный обработчик и обновляет содержимое контейнера с id app.
Управление состоянием приложения
Состояние — это данные, которые меняются со временем. Например, список товаров в корзине или текущий пользователь. В SPA состояние хранят в объекте и обновляют через функции.
const state = {
items: [],
currentUser: null,
loading: false
};
function addItem(item) {
state.items.push(item);
render(); // перерисовываем интерфейс
}
function removeItem(id) {
state.items = state.items.filter(item => item.id !== id);
render();
}
function render() {
const list = document.getElementById('list');
list.innerHTML = state.items.map(item => `${item.name} `).join('');
}
Главное правило: не меняйте DOM напрямую. Сначала обновите состояние, потом вызовите render. Это сделает код предсказуемым.
Работа с сервером: загрузка данных
SPA часто общается с сервером через API. Используем fetch для получения данных. Вот пример загрузки списка пользователей:
async function loadUsers() {
state.loading = true;
render();
try {
const response = await fetch('/api/users');
const users = await response.json();
state.users = users;
state.loading = false;
render();
} catch (error) {
state.error = 'Ошибка загрузки';
state.loading = false;
render();
}
}
Обратите внимание: мы показываем индикатор загрузки (state.loading), потом скрываем его. Это улучшает пользовательский опыт. Если произошла ошибка — показываем сообщение.
Сборка всего вместе: пример SPA
Теперь давайте соберём мини-приложение: список задач с возможностью добавлять и удалять. Вот полный код:
В этом примере всё в одном файле. В реальном проекте вы бы разбили код на модули, но для обучения сойдёт.
| Компонент | Описание | Пример |
|---|---|---|
| Роутер | Управляет навигацией | hashchange |
| Состояние | Хранит данные | Объект state |
| Рендер | Обновляет DOM | innerHTML |
| Обработчики | Реагируют на действия | addEventListener |
Итог
Мы разобрали, как создать простое SPA на чистом JavaScript. Вы узнали про роутер, состояние, рендер и работу с сервером. Теперь вы можете написать своё приложение без фреймворков. Начните с малого: список задач или простой блог. Со временем вы сможете добавить модульность, шаблоны и даже свой мини-фреймворк.
Помните: SPA — это не магия, а просто JavaScript, который обновляет страницу по частям. Не бойтесь экспериментировать и пишите код с удовольствием.



