2 - Front-end без фреймворков - Vanilla UI

Оценить качество материала и подачу материала автором видео:

Front-end

Трудоустройтесь middle front-end разработчиком на React JS (TypeScript) за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Front-end

Back-end

Трудоустройтесь middle back-end разработчиком за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Back-end

Карьерный бустер

Получите коммерческий опыт на реальных стартапах, прокачайте tech & soft навыки, научитесь работать в команде, проходить собеседования и получите первую работу в IT!

Перейти на курс
Карьерный бустер

Основы Front-end

Сделайте первый шаг в IT, освоив базовые знания разработки и научившись создавать небольшие проекты на JavaScript

Перейти на курс
Основы Front-end

Основы Back-end

Сделайте первый шаг в IT, освоив базовые знания разработки. Без опыта. Без математики. Только практика: JavaScript, SQL, Node JS, база данных

Перейти на курс
Основы Back-end

Vanilla front

Автор конспекта: Арина Василевская

Полезные ссылки:

Функционирование frontend-приложения

Схема начала работы фронтенд-приложения может быть представлена следующим образом:

startApp

  1. Пользователь открывает браузер.
  2. Вводит адрес сайта в адресной строке.
  3. Браузер через DNS определяет IP-адрес сервера и отправляет HTTP-запрос.
  4. Сервер по адресу понимает, какой файл нужно вернуть (например, index.html).
  5. HTML-файл загружается в браузер.
🖥️

Сервер — это комбинация:

🔵 Компьютер в дата-центре, всегда подключенный к Интернету

🔵 Программное обеспечение, которое обрабатывает запросы

HTML как контейнер приложения

  • В классическом сайте HTML содержит много тегов и статическую вёрстку.
  • В современном frontend-приложении index.html — это контейнер, в котором оживает приложение на JavaScript.
  • Внутри обычно есть:
html
<div id="root"></div>

Этот элемент служит контейнером для всего приложения. Идентификатор может быть любым, но чаще всего — root, app или main.

Без JavaScript страница выглядит «пустой» — приложение оживает только после загрузки JS-кода.

Декомпозиция приложения

JavaScript-код разделяется на два файла:

index.html
<script src="data.js"></script>
<script src="ui.js"></script>
  • Работа с данными (data.js) — бизнес-логика, хранение данных.
  • Работа с отрисовкой (ui.js) — отвечает за отрисовку и визуализацию данных (UI). Такая декомпозиция помогает отделить логику от представления.

В атрибуте src тега script указываем, откуда загружать скрипт.

Парсинг HTML и DOM

Для браузера index.html — это просто текст. Он парсит(читает) текст скрипта, разбирает его на теги, атрибуты и превращает их в DOM-дерево. DOM — это древовидная иерархия объектов, которая описывает структуру документа. JS работает именно с DOM-объектами, а не с «тегами» как строками. Изменения в DOM автоматически отображаются браузером.

🌳

DOM (Document Object Model) — древовидная модель, которая представляет HTML-документ как объект, доступный для чтения и изменения через JavaScript.

🔗

Ссылка на статью DOM (doka)

Работа с данными (data.js)

Файл данных обычно содержит:

  • Объекты
  • Массивы
  • Массивы объектов

Это позволяет удобно хранить и обрабатывать информацию (например, список треков).

js
const tracks = [
  { id: 1, title: "Song A", src: "song-a.mp3" },
  { id: 2, title: "Song B", src: "song-b.mp3" },
]

Файл загружается и выполняется первым.

Работа с UI (ui.js)

  • Загружается после data.js (т.к. подключён в index.html после него).
  • Не хранит данные, а отвечает только за их отрисовку.
  • Ищет root-элемент по id:
js
const root = document.getElementById("root")
  • Создаёт новые DOM-элементы. С помощью forEach пробегаемся по массиву треков и для каждого трека выполняем последовательность действий:
js
const listEl = document.createElement("ul") //создаём список (ul) треков.
tracks.forEach((track) => {
  const itemEl = document.createElement("li") //создаём элемент списка (li) для трека
  const audioEl = document.createElement("audio") //создаём аудиоэлемент (audio)
  audioEl.src = track.src //задаём src (адрес аудиофайла)
  itemEl.append(audioEl) //вставляем аудио в элемент списка
  listEl.append(itemEl) //вставляем список в элемент root
})
root.append(listEl)
🔗

Ссылка на документацию MDN forEach

Практика с Vanilla JS

Пока у нас нет никаких фреймворков, мы работаем с так называемым Vanilla JS.

💡

Vanilla JS — это нативный ("чистый") JavaScript без использования библиотек и фреймворков (например, React или Angular).

Редакторы кода

Для написания кода можно использовать:

  • WebStorm — IDE «из коробки» со всеми настройками (автогенерация кода, подсказки, интеграция с фреймворками).
  • VS Code или другой редактор — также подойдёт, дело вкуса. Рекомендуем WebStorm начинающим, так как он избавляет от ручных настроек и позволяет сразу сосредоточиться на коде и логике.
🔗

Ссылки на редакторы: WebStorm, VS Code

Создание html страницы

  1. Создаем файл index.html
  2. Чтобы сгенерировать базовую разметку в WebStorm используем комбинацию ! + Tab
  3. Пока убираем <head>
  4. В <body> добавляем простую структуру с заголовком и списком.
index.html
<html lang="en">
  <body>
    <div id="root">
      <h1>Musicfun player</h1>
      <ul>
        <li>Musicfun soundtrack</li>
        <li>Musicfun soundtrack instrumental</li>
      </ul>
    </div>
  </body>
</html>

Запуск страницы в браузере

Два варианта запуска HTML-страницы:

  1. ❌ Неправильный способ
  • Мы можем просто взять файл index.html и перетащить его в браузер.
  • В этом случае в адресной строке будет:
text
file:///Users/.../index.html
  • Это значит, что браузер прочитал файл прямо с диска (как будто открыл документ Word или PDF).

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

  1. ✅ Правильный способ — через сервер. Чтобы страница вела себя как настоящий сайт, нужен программный сервер.

В WebStorm

  • Кликаем правой кнопкой → Run index.html.
  • WebStorm поднимает встроенный сервер и открывает страницу в браузере.

В VS Code

  • Ставим расширение Live Server
  • Кликаем правой кнопкой на index.html → Open with Live Server.
🔗

Расширение можно установить с сайта Live Server или через вкладку расширений в VS Code

Теперь страница открывается по HTTP-протоколу с адресом:

text
http://localhost:3000/index.html

Что такое localhost и порт

  • localhost — особое доменное имя. Браузер понимает его как «обратись к самому себе». То есть запрос не идёт в интернет, а возвращается на этот же компьютер.
  • Железным сервером в данном случае выступает сам ноутбук/ПК.
  • Программным сервером выступает софт (WebStorm, Live Server и т.д.), который слушает определённый порт и отдаёт файлы.
ℹ️

Номер порта нужен, чтобы несколько программ на одном компьютере могли работать с сетью одновременно. Каждая «занимает» свой порт.

Добавляем музыку 🎵 на страницу

  1. В <li> вставляем тег <audio>
  2. Тег <audio> отображается в браузере только если есть атрибут controls
  3. В src указываем ссылку на .mp3
🔗

Ссылки на треки можно взять здесь 👉 MusicfunApi

🎉 Получается минимальный музыкальный плеер на чистом HTML.

index.html
<ul>
  <li>
    <div>Musicfun soundtrack</div>
    <audio controls src="https://musicfun.it-incubator.app/api/samurai-way-soundtrack.mp3"></audio>
  </li>
  <li>
    <div>Musicfun soundtrack instrumental</div>
    <audio
      controls
      src="https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3"
    ></audio>
  </li>
</ul>

Проверка в DevTools → Network

  • Открываем вкладку Network (F12 → Network). Обновляем страницу:

Network

  1. Загружается наш index.html.
  2. Подтягиваются встроенные картинки (дефолтные кнопки плеера).
  3. Запрашиваются музыкальные файлы с сервера (.mp3). При первой подгрузке загружается только превью, а не весь трек. А уже при нажатии play загружается полный трек.
  4. Устанавливается WebSocket-соединение для автообновления страницы.
  5. Подгружается фавиконка

Создание frontend-приложения

🤔 Так зачем нам всё-таки делать HTML пустым и оживлять его с помощью JS, если всё работает и без этого?

  • Статический HTML — это как написанное «на бумаге»: данные зафиксированы и не меняются.

Но данные в реальности динамичны:

  • могут появляться новые треки, изменяться названия, ссылки;

  • возможны сортировки, фильтры, лайки, подписки и т.п.

  • Если всё «зашить» прямо в HTML, придётся вручную копировать-разметку и править её. Это неудобно и не масштабируется.

Поэтому HTML делают максимально пустым (например, только <div id="root"></div>). Дальше всё наполняется с помощью JS, который:

  1. берёт данные (массив объектов треков);
  2. по алгоритму создаёт DOM-элементы (заголовки, списки, плееры);
  3. вставляет их на страницу.

Редактируем наш код

  1. Создаем файл main.js
  2. Из index.html удаляем все лишнее
  3. Подключаем main.js в index.html
index.html
<html lang="en">
  <body>
    <div id="root"></div>
    <script src="main.js"></script>
  </body>
</html>

Описываем данные

Создаем массив tracks с объектами треков, которые содержат название трека(title) и ссылку на сам аудиофайл(url):

main.js
const tracks = [
  {
    title: "Musicfun soundtrack",
    url: "https://musicfun.it-incubator.app/api/samurai-way-soundtrack.mp3",
  },
  {
    title: "Musicfun soundtrack instrumental",
    url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
  },
]
💡

Разделение данных и логики отрисовки упрощает поддержку кода (maintainability) — новые треки можно добавлять без изменения алгоритма.

Создание элементов

  • Находим наш корневой <div> по id. Используем document.getElementById("root").
  • Все новые элементы вставляются внутрь него.
main.js
const rootEl = document.getElementById("root") // Находим наш корневой <div> по id
const headerEl = document.createElement("h1") // создаем тег заголовка для страницы
headerEl.append("Musicfun Player") // добавляем текст в заголовок
rootEl.append(headerEl) //добавляем заголовок в корневой div
 
const tracksEl = document.createElement("ul") //создаем список треков

Теперь для каждого трека нам необходимо создать:

  • li — обёртка для трека
  • div с названием трека;
  • audio с атрибутом controls и src = track.src

Для обхода массива с данными воспользуемся методом массива forEach:

main.js
tracks.forEach((track) => {
  const trackEL = document.createElement("li") //создаем элемент трека
  const trackTitleEL = document.createElement("div") // создаем элемент для заголовка трека
  trackTitleEL.append(track.title) // добавляем заголовок трека в наш div
  trackEL.append(trackTitleEL) //добавляем элемент заголовка в трек
 
  const trackPlayerEL = document.createElement("audio") //создаем тег audio
  trackPlayerEL.controls = true // говорим, что нам нужен интерфейс управления аудио
  trackPlayerEL.src = track.url //добавляем ссылку на наш файл
  trackEL.append(trackPlayerEL) // и добавляем весь аудио элемент в наг трек
 
  tracksEl.append(trackEL) //добавляем трек в список треков
})
rootEl.append(tracksEl) // и теперь добавляем список треков в наш корневой div-элемент

🚀 Вот и готово первое frontend-приложение!

Важные архитектурные идеи

  • разделение данных и рендеринга: данные → массив объектов, рендеринг → алгоритм отрисовки;
  • добавление новых треков не требует менять логику.
  • DOM-дерево динамическое: изначально пустое, браузер наполняет его из JS.
  • Алгоритм универсален: работает одинаково для любого количества данных.

Недостатки нативного подхода

  • Код быстро становится громоздким:
  • множество createElement, append, вложенностей;
  • сложно читать структуру;
  • при условной отрисовке появляются if/else, усложняющие код.
  • Вёрстка современных приложений слишком сложная, чтобы делать всё руками.

Тут на помощь приходят фреймворки (React, Vue, Angular) со своими преимуществами:

  • упрощают работу с DOM (не нужно вручную создавать и вкладывать элементы);
  • автоматически обновляют интерфейс при изменении данных;
  • позволяют сосредоточиться на данных и бизнес-логике, а не на работе с DOM.

❗Нативный JS не теряет свою важность! Чтобы быть профессионалами своего дела мы должны:

  • понимать, что делает фреймворк «под капотом».
  • оценивать «стоимость» операций в DOM.
  • уметь дебажить проблемы производительности.

🏠 Домашнее задание

Создание списка дел

  • Цель задания

Применить полученные знания о работе с DOM для создания интерактивного списка дел (Trelly).

  • Задача

На основе изученного примера с музыкальным плеером создать веб-страницу со списком дел, где каждая задача имеет название и статус выполнения.

Требования

Структура данных

Создайте массив объектов tasks с задачами, где каждый объект содержит:

  • title (string) - название задачи
  • isDone (boolean) - статус выполнения (true/false)

Пример данных

javascript
const tasks = [
  { title: "Купить продукты на неделю", isDone: false },
  { title: "Полить цветы", isDone: true },
  { title: "Сходить на тренировку", isDone: false },
]

HTML-структура

Создайте следующую структуру:

  1. Заголовок - элемент h1 с текстом "Список дел"
  2. Список задач - элемент ul со списком всех задач
  3. Каждая задача должна быть элементом li, содержащим:
  • div с названием задачи
  • input типа checkbox для отображения статуса выполнения

Технические детали

Обязательные элементы и свойства:
  • Получите корневой элемент через document.getElementById('root')
  • Создавайте элементы через document.createElement()
  • Добавляйте текст через метод .append()
  • Устанавливайте тип чекбокса: taskStatusEL.type = 'checkbox'
  • Устанавливайте состояние чекбокса: taskStatusEL.checked = task.isDone
Алгоритм выполнения:
  1. Создайте и добавьте заголовок
  2. Создайте контейнер для списка задач (ul)
  3. Переберите массив задач через forEach
  4. Для каждой задачи создайте:
  • Элемент списка (li)
  • Div с названием задачи
  • Чекбокс с соответствующим состоянием
  1. Соберите все элементы в правильной иерархии

Ожидаемый результат

После выполнения задания на странице должен отобразиться список из трёх дел:

  • "Купить продукты на неделю" (не выполнено)
  • "Полить цветы" (выполнено - чекбокс отмечен)
  • "Сходить на тренировку" (не выполнено)

result

Что делать если что-то пошло не так

🔗

Если в процессе прохождения домашнего задания возникнут сложности переходи в комнату help2debug, где ты сможешь получить поддержку со стороны других участников сообщества.

Дополнительно (по желанию)

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

Боевой маршрут (React Путь Самурая: без альтернатив)

Видеоурок - 3 видео из 30