Веб-приложения на языке JavaScript: практические примеры и решения

Раздел: Программирование -> Основы языка JavaScript

Способы построения приложений на JavaScript

Создание интерактивных страниц и полноценных веб-приложений - одна из главных задач JavaScript. Рассмотрим несколько подходов, отличающихся по сложности и производительности, начиная с чистого языка и заканчивая использованием готовых библиотек.

Как реализовать одностраничное приложение без фреймворков?

Самый прозрачный способ - использовать чистый JavaScript с управлением маршрутами через hashchange и динамическим рендерингом. Это даёт полный контроль над кодом и лучше понимание внутренних механизмов.

Алгоритм:

  1. Определить структуру SPA (Single Page Application) с главным контейнером #app.
  2. Реализовать функцию-роутер, которая анализирует window.location.hash и вызывает соответствующий рендер.
  3. Создать функции рендеринга для каждой страницы (например, renderHome(), renderAbout()).
  4. Подписаться на событие hashchange и запускать роутер при загрузке.
// index.html
<nav>
  <a href="#/home">Главная</a>
  <a href="#/about">О нас</a>
</nav>
<div id="app"></div>

<script src="app.js"></script>

Find js (поиск в javascript)

// app.js
const app = document.getElementById('app');

function router() {
  const hash = window.location.hash.slice(1) || '/home';
  const routes = {
    '/home': renderHome,
    '/about': renderAbout
  };
  const render = routes[hash] || renderNotFound;
  app.innerHTML = render();
}

function renderHome() {
  return '<h2>Главная страница</h2><p>Добро пожаловать!</p>';
}
function renderAbout() {
  return '<h2>О нас</h2><p>Создано на чистом JS.</p>';
}
function renderNotFound() {
  return '<h2>404</h2><p>Страница не найдена</p>';
}

window.addEventListener('hashchange', router);
window.addEventListener('load', router);

Js примеры (примеры кода на javascript)

Результат: при клике по ссылкам меняется содержимое #app без перезагрузки страницы.

Javascript строки (строки в javascript)

Типичные ошибки:

  • Забыть подписаться на load, и начальная страница не отображается.
  • Неправильное значение hash - нужно использовать window.location.hash без ошибок.
  • Инъекция HTML через innerHTML - для пользовательского ввода требуется санитизация.

Цель: подходит для небольших проектов, портфолио, учебных примеров.

Как упростить работу с DOM и событиями в приложении?

Библиотека jQuery предлагает лаконичный синтаксис для манипуляций, анимаций и AJAX. Она удобна, когда проект уже использует устаревший код или нужна быстрая совместимость с IE.

// подключение jQuery (через CDN)
 <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
 <div id="content"></div>
 <script>
   // Навигация с помощью jQuery
   $(document).ready(function() {
     function loadPage(hash) {
       const pages = {
         'home': '<h2>Домой</h2>',
         'about': '<h2>О проекте</h2>'
       };
       $('#content').html(pages[hash] || '<h2>404</h2>');
     }
     $(window).on('hashchange', function() {
       var hash = location.hash.slice(1) || 'home';
       loadPage(hash);
     }).trigger('hashchange');
   });
 </script>

Js фильтр (фильтрация в javascript)

Результат: тот же принцип SPA, но короче за счёт цепочек jQuery.

Meta js (мета-теги в javascript)

Проблемы:

  • Устаревший подход, современные проекты редко используют jQuery.
  • Избыточная загрузка библиотеки для небольших задач.
  • Не решает проблему управления состоянием и сложной логики.

Как быстро создать реактивное приложение с компонентами?

React - современная библиотека для построения UI. Использование JSX, компонентов и виртуального DOM упрощает разработку масштабируемых приложений. Пример - та же маршрутизация с помощью react-router-dom.

// App.jsx
import React from 'react';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';

function Home() { return <h2>Главная</h2>; }
function About() { return <h2>О нас</h2>; }

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Домой</Link>
        <Link to="/about">О проекте</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}
export default App;

Href javascript (ссылки javascript)

Результат: полноценная SPA с навигацией, поддерживающая вложенные маршруты и lazy loading.

Возможные сложности:

  • Необходимость сборщика (Webpack, Vite).
  • Кривая обучения для начинающих.
  • Избыток абстракций для простых сайтов.

Расширенные примеры создания приложений на JavaScript

Чистое SPA с загрузкой данных и сохранением состояния

В этом примере используется localStorage для хранения избранных элементов и fetch для получения списка постов с JSONPlaceholder. Реализована обработка ошибок при загрузке.

Пример
// advanced-app.html
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Расширенное SPA</title></head>
<body>
  <nav>
    <a href="#/posts">Посты</a>
    <a href="#/favorites">Избранное</a>
  </nav>
  <div id="app"></div>
  <div id="status"></div>
  <script type="module">
    const app = document.getElementById('app');
    const status = document.getElementById('status');

    // Состояние приложения
    let favorites = JSON.parse(localStorage.getItem('favorites')) || [];

    function saveFavorites() {
      localStorage.setItem('favorites', JSON.stringify(favorites));
    }

    function renderStatus(msg, isError = false) {
      status.innerHTML = isError ? `<p style="color:red">${msg}</p>` : `<p>${msg}</p>`;
    }

    async function renderPosts() {
      app.innerHTML = '<p>Загрузка...</p>';
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts');
        if (!response.ok) throw new Error('Ошибка HTTP: ' + response.status);
        const posts = await response.json();
        let html = '<h2>Посты</h2><ul>';
        posts.slice(0, 10).forEach(post => {
          const isFav = favorites.includes(post.id);
          html += `<li>${post.title} <button data-id="${post.id}" class="fav-btn">${isFav ? 'Убрать' : 'В избранное'}</button></li>`;
        });
        html += '</ul>';
        app.innerHTML = html;

        // Обработка кликов по кнопкам избранного
        app.querySelectorAll('.fav-btn').forEach(btn => {
          btn.addEventListener('click', (e) => {
            const id = Number(e.target.dataset.id);
            const idx = favorites.indexOf(id);
            if (idx === -1) {
              favorites.push(id);
              renderStatus('Добавлено в избранное');
            } else {
              favorites.splice(idx, 1);
              renderStatus('Удалено из избранного');
            }
            saveFavorites();
            renderPosts(); // обновление списка
          });
        });
      } catch (error) {
        renderStatus(error.message, true);
        app.innerHTML = '<p>Не удалось загрузить посты.</p>';
      }
    }

    function renderFavorites() {
      if (favorites.length === 0) {
        app.innerHTML = '<h2>Избранное</h2><p>Пока ничего нет.</p>';
        return;
      }
      // Загружаем посты, соответствующие избранным ID
      fetch('https://jsonplaceholder.typicode.com/posts')
        .then(res => res.json())
        .then(posts => {
          const favPosts = posts.filter(p => favorites.includes(p.id));
          let html = '<h2>Избранные посты</h2><ul>';
          favPosts.forEach(p => {
            html += `<li>${p.title}</li>`;
          });
          html += '</ul>';
          app.innerHTML = html;
        })
        .catch(err => renderStatus(err.message, true));
    }

    function router() {
      const hash = location.hash.slice(1) || '/posts';
      if (hash === '/posts') renderPosts();
      else if (hash === '/favorites') renderFavorites();
      else app.innerHTML = '<h2>404</h2>';
    }

    window.addEventListener('hashchange', router);
    window.addEventListener('load', router);
  </script>
</body>
</html>
Результат: посты загружаются с сервера, можно добавлять/удалять избранное, данные сохраняются в localStorage. 

Создание приложения с помощью классов ES6

Организация кода в виде классов улучшает читаемость и модульность. Пример простого слайдера изображений.

Пример
class ImageSlider {
  constructor(container, images) {
    this.container = container;
    this.images = images;
    this.current = 0;
    this.render();
  }
  render() {
    this.container.innerHTML = `
      <img id="slider-img" src="${this.images[this.current]}" style="width:400px" />
      <div>
        <button id="prev">Назад</button>
        <button id="next">Вперёд</button>
      </div>
    `;
    this.bindEvents();
  }
  bindEvents() {
    document.getElementById('prev').addEventListener('click', () => this.prev());
    document.getElementById('next').addEventListener('click', () => this.next());
  }
  prev() {
    this.current = (this.current - 1 + this.images.length) % this.images.length;
    this.updateImage();
  }
  next() {
    this.current = (this.current + 1) % this.images.length;
    this.updateImage();
  }
  updateImage() {
    document.getElementById('slider-img').src = this.images[this.current];
  }
}

// Использование
const images = [
  'https://picsum.photos/id/10/400/300',
  'https://picsum.photos/id/20/400/300',
  'https://picsum.photos/id/30/400/300'
];
const container = document.getElementById('slider-container');
const slider = new ImageSlider(container, images);
Результат: слайдер с кнопками, работающими по кругу. Код инкапсулирован в класс.

Приложения на JavaScript - comments

En
Js приложения (javascript)