Курс: Создание веб-приложений с использованием Angular и React

Урок №1

Современная веб-разработка: как устроено веб-приложение

Теория — 90 минут
Практика — 60 минут

Сквозной проект курса: TaskFlow

Путь от пользователя до данныхПользовательдействие, ввод,переходБраузерHTML, CSS, JS/TS, UIAPIHTTP-запросы и ответыBackendбизнес-правила ибезопасностьDatabaseдолговременноесостояние
Общая карта приложения.

Студенческий материал. Его можно использовать как самостоятельный конспект, раздаточный материал и справочник после занятия.

Содержание

  1. 1. Зачем вообще понимать архитектуру веб-приложения
  2. 2. Что такое веб-приложение
  3. 3. Браузер - первая среда выполнения frontend
  4. 4. URL: как браузер понимает, куда идти
  5. 5. DNS: как доменное имя становится сетевым адресом
  6. 6. HTTP: запрос и ответ
  7. 7. REST API как контракт
  8. 8. JSON - язык данных, а не интерфейс
  9. 9. HTML: каркас страницы
  10. 10. CSS: представление без бизнес-логики
  11. 11. JavaScript: поведение и события
  12. 12. DOM и почему декларативный UI удобен
  13. 13. TypeScript: типы как внутренний контракт
  14. 14. Promise, async/await и реальное время сети
  15. 15. Frontend и backend: разные ответственности
  16. 16. SPA, MPA и зачем нужен клиентский роутинг
  17. 17. CSR, SSR, SSG и hydration
  18. 18. Framework и library: как сравнивать Angular и React
  19. 19. Angular 2026: современная точка отсчёта
  20. 20. Angular component: первый взгляд
  21. 21. Angular template: данные и события
  22. 22. React 2026: базовая ментальная модель
  23. 23. React: props и композиция
  24. 24. Общее и различное в Angular и React
  25. 25. Node.js, npm и package.json
  26. 26. Git: минимальный рабочий цикл
  27. 27. DevTools: Console и Network как обязательные инструменты
  28. 28. Accessibility: интерфейс должен быть понятен не только мыши
  29. 29. Безопасность: границы доверия
  30. 30. Производительность: что влияет на скорость
  31. 31. State: минимальное состояние и производные данные
  32. 32. Local state и server state
  33. 33. Loading, empty, error — четыре состояния UI
  34. 34. Как проектировать TaskFlow до кода
  35. 35. Практика: подготовка окружения
  36. 36. Практика: первый локальный Angular-проект
  37. 37. Практика: первый компонент списка задач
  38. 37.1. Практика: подключение компонента к корню
  39. 38. Практика: первый React-компонент
  40. 39. Практика: сравнить одну и ту же задачу
  41. 40. Практика: сделать состояние видимым
  42. 41. Почему входная диагностика не нужна в раздаточном материале
  43. 42. Самопроверка: связать всё в одну систему
  44. 43. Что будет на следующих занятиях Angular
  45. 44. Что будет на следующих занятиях React
  46. 45. Домашнее задание
  47. 46. Контрольные вопросы
  48. Ответы и подсказки к заданиям
  49. 47. Мини-словарь
  50. 48. Источники и актуализация материала
  51. 48A. Если что-то не запускается: базовая диагностика
  52. 49. Практическая лаборатория: от клика до HTTP
  53. 50. Практическая лаборатория: три состояния UI
  54. 51. Практическая лаборатория: минимальная модель Task
  55. 52. Практическая лаборатория: компонентное дерево
  56. 53. Практическая лаборатория: сравнение Angular и React без копирования кода
  57. 54. Финальная страница урока: что должно остаться в голове
Урок 1 • Раздел 1

1. Зачем вообще понимать архитектуру веб-приложения

Angular и React появляются в нашем курсе не в качестве магических инструментов, а как следующий слой над базовыми механизмами веба.

Если студент начинает с команды генерации проекта, он довольно быстро получает экран в браузере, но не понимает, что именно делает framework. При первой нестандартной ошибке такой навык ломается. Поэтому первый урок строится от основания: браузер, HTTP, HTML, CSS, JavaScript, данные, компоненты и только затем Angular и React.

Аналогия. Представьте TaskFlow как холодильник с магнитиками-заметками: пользователь добавляет новую заметку, перечёркивает выполненную, отбирает только важные. Чтобы собрать такой «холодильник» на компьютере, нам нужно сделать несколько вещей сразу: нарисовать интерфейс, запомнить, что уже сделано (состояние), откликаться на нажатия, обращаться к серверу за данными, ловить ошибки и держать код в порядке, чтобы его можно было расширять.

В этом уроке мы создадим общую карту. Вы не обязаны запомнить каждую команду. Важнее к концу занятия уметь ответить на вопрос: какая часть системы отвечает за данный процесс?

const state = {
  tasks: [{ id: 1, title: "Изучить HTTP", completed: false }],
  filter: "all",
  loading: false
};

// после клика "Выполнено"
state.tasks[0].completed = true;
// UI должен показать зачёркнутый текст
Контекст. Это «снимок» состояния приложения TaskFlow в один момент времени. Такой объект state будет жить в любом компоненте — и в Angular, и в React.
Аналогия из жизни. state — как листок с текущим статусом заказа в пиццерии: «в работе / готов / ошибка». Пока статус не поменялся, повара и клиент смотрят в один и тот же листок.
Разбор по шагам:
  1. tasks — массив задач; у каждой есть id, title и флаг completed.
  2. filter — что показываем: "all" (все), "active" (не сделанные) или "done" (сделанные). done здесь — значение фильтра, а НЕ поле задачи!
  3. loading — идёт ли сейчас загрузка с сервера.
  4. Строка state.tasks[0].completed = true меняет флаг первой задачи.
Что увидит пользователь: задача «Изучить HTTP» станет перечёркнутой, потому что интерфейс «подсмотрел» изменение состояния.
Запомните: статическая веб-страница — это документ. Веб-приложение — это программа с состоянием, логикой и интерактивностью. Angular и React создают именно веб-приложения.
Главная идея. Web framework не отменяет веб-платформу. Angular и React работают поверх браузера, JavaScript/TypeScript, HTTP, DOM и CSS.
Путь от пользователя до данныхПользовательдействие, ввод,переходБраузерHTML, CSS, JS/TS, UIAPIHTTP-запросы и ответыBackendбизнес-правила ибезопасностьDatabaseдолговременноесостояние
Рисунок 1. Упрощённая архитектура приложения TaskFlow.
Урок 1 • Раздел 2

2. Что такое веб-приложение

Веб-приложение - это программа, которой пользователь управляет через веб-браузер. В отличие от обычного документа, приложение хранит некоторое состояние и меняет интерфейс в ответ на действия пользователя или новые данные.

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

Поэтому полезно различать содержимое и поведение. HTML описывает структуру, CSS - визуальное представление, JavaScript - поведение. Angular и React помогают организовать поведение и представление сложного интерфейса.

Какие свойства есть у приложения?

В TaskFlow состояние может включать список задач, выбранный фильтр, содержимое формы и состояние загрузки. Уже здесь видно, что UI - это не просто HTML-файл. Это визуальное представление данных и состояния.

Урок 1 • Раздел 3

3. Браузер - первая среда выполнения frontend

Браузер одновременно является программой для просмотра страниц и средой выполнения frontend-кода. Он загружает ресурсы, создаёт DOM, применяет CSS, выполняет JavaScript, обрабатывает события и выполняет сетевые запросы.

После получения HTML браузер строит структуру документа. JavaScript может найти элементы, изменить их содержимое или классы, зарегистрировать обработчики событий и запросить дополнительные данные. Именно поэтому пользователь может взаимодействовать с интерфейсом без полной перезагрузки страницы.

Современный frontend использует эти возможности косвенно. Angular и React предоставляют свой способ описывать UI, но конечная работа всё равно происходит в браузере. Если вы понимаете DOM и события, вы будете лучше понимать и работу framework.

DevTools как учебный инструмент

Откройте DevTools. Откройте DevTools: нажмите F12 (Windows/Linux) или Cmd+Option+I (Mac). Или щёлкните правой кнопкой мыши на странице → «Просмотреть код». В Console мы увидим сообщения и runtime-ошибки. Во вкладке Network можно посмотреть реальные запросы. В Elements можно увидеть DOM, который браузер получил после работы приложения. Это три разных окна в одну и ту же систему.

Практическое правило. Когда интерфейс «не работает», сначала определите уровень проблемы: DOM/JS, HTTP или backend. Не начинайте случайно менять CSS и компоненты.
Урок 1 • Раздел 4

4. URL: как браузер понимает, куда идти

URL описывает ресурс и способ обращения к нему. В простой форме мы видим схему, хост и путь. В приложениях появляются query-параметры и фрагменты.

https://taskflow.example/tasks/42?completed=false#details

Здесь https - схема, taskflow.example - хост, /tasks/42 - путь, ?completed=false - query string, #details - fragment. Для frontend особенно важен путь: он может означать маршрут интерфейса или адрес ресурса API.

Например, Angular Router или React Router могут сопоставлять путь /tasks/42 с экраном задачи. При этом API может использовать /api/tasks/42. Сходство имён не означает, что это один и тот же механизм.

Важно. Fragment после символа # обычно не отправляется серверу как часть HTTP-запроса. Это значение, связанное с клиентской частью URL.
Урок 1 • Раздел 5

5. DNS: как доменное имя становится сетевым адресом

Людям удобнее запоминать доменные имена, а сетевые соединения используют адреса узлов. DNS связывает эти представления. Когда приложение открывается по имени, браузеру и операционной системе нужно получить информацию, позволяющую установить соединение.

Для frontend-разработчика DNS важен как часть диагностики. Если домен не разрешается, а приложение работает по IP, причина может быть вообще не в frontend-коде. Если соединение не устанавливается, поиск ошибки в компоненте не даст результата.

В production архитектура может содержать несколько DNS-записей: отдельный домен для приложения, API, статических ресурсов, CDN и других сервисов. Это одна из причин, почему полезно понимать систему целиком.

Запомните. Сбой до установления HTTP-соединения не является «ошибкой React-компонента» или «ошибкой Angular template». Сначала определяем уровень.
Урок 1 • Раздел 6

6. HTTP: запрос и ответ

HTTP - базовый протокол взаимодействия веб-клиента и сервера. Для frontend важны метод, URL, заголовки, тело и статус ответа.

GET /api/tasks/42 HTTP/1.1
Host: taskflow.example
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 42,
  "title": "Изучить HTTP"
}
Контекст. Реальный обмен между браузером TaskFlow и сервером: мы просим задачу с id=42.
Аналогия из жизни. HTTP-запрос — как заказ в магазине: вы подходите к прилавку (/api/tasks), говорите «дайте мне вот это» (метод GET), а продавец либо даёт посылку (ответ 200 + JSON), либо «нет в наличии» (404), либо «не положено» (403).
Разбор по шагам:
  1. Команда GET — «покажи список задач».
  2. Заголовки Host и Accept уточняют сервер и формат ответа (JSON).
  3. Ответ начинается со статуса 200 OK — всё хорошо.
  4. Тело ответа — JSON-объект с id и title.
Что увидит пользователь: в списке задач появится строка «Изучить HTTP».

Метод GET обычно используется для получения данных, POST - для создания или выполнения операции, PATCH - для частичного изменения, PUT - для замены ресурса, DELETE - для удаления. В реальном API встречаются дополнительные правила, но эта схема полезна как база.

Статус-код - ещё один обязательный элемент чтения ответа. 2xx обычно означает успех. 4xx указывает на проблему запроса клиента или его прав. 5xx - на ошибку сервера. Frontend должен обрабатывать эти состояния явно.

Практика мышления. Если кнопка «Сохранить» не работает, откройте Network и ответьте: был ли запрос, какой URL, какой метод, какой status и что пришло в Response?
Урок 1 • Раздел 7

7. REST API как контракт

💡 Почему REST? REST опирается на стандартные HTTP-методы (GET, POST, PATCH, DELETE) и адреса ресурсов. Благодаря этому frontend и backend понимают друг друга без частных соглашений — один и тот же стиль работает в любом языке и фреймворке.

API задаёт правила общения frontend и backend. Хороший API позволяет клиенту знать, какие операции доступны и какой формат данных ожидается. Это особенно важно, когда две команды работают независимо.

Для TaskFlow мы можем определить простую модель CRUD: список задач, получение одной задачи, создание, изменение и удаление. Контракт описывает не только URL, но и поля, типы, обязательность, возможные ошибки.

В зрелом проекте API может описываться средствами OpenAPI. Тогда frontend может опираться на формальный контракт, а часть клиентов и типизации может генерироваться автоматически.

ОперацияМетодEndpointЧто получает клиент
СписокGET/api/tasksTask[]
Одна задачаGET/api/tasks/42Task
СозданиеPOST/api/tasksСозданная Task
ИзменениеPATCH/api/tasks/42Обновлённая Task
УдалениеDELETE/api/tasks/42Статус операции

В production API обычно используют префикс /api. В наших учебных упражнениях с json-server используется более короткий путь /tasks.

Урок 1 • Раздел 8

8. JSON - язык данных, а не интерфейс

💡 Почему JSON? JSON — текстовый формат, который легко читает человек и однозначно разбирает почти любой язык. Он стал «общим языком» веба: сервер отдаёт JSON, а JS превращает его в обычный объект без дополнительных библиотек.

JSON часто используется в HTTP API, потому что он компактный и легко преобразуется в объекты JavaScript. Но JSON содержит только данные. В нём нет методов класса, обработчиков или UI.

{
  "id": 42,
  "title": "Изучить JSON",
  "completed": false,
  "tags": ["web", "frontend"],
  "owner": null
}
Контекст. Так сервер TaskFlow отдаёт одну задачу: с тегами и без владельца.
Аналогия из жизни. JSON — как этикетка на посылке: на ней написаны «поле: значение» парами. Сервер «наклеивает» такую этикетку, а браузер её «читает».
Разбор по шагам:
  1. id и title — как в предыдущем примере.
  2. completedfalse, значит задача ещё не выполнена.
  3. tags — это массив (список) строк, как несколько ярлыков на папке.
  4. owner: null — владелец пока не задан (пусто).

На frontend эти данные обычно превращаются в структуры, с которыми работает приложение. TypeScript позволяет описать ожидаемую форму данных, но не гарантирует, что удалённый сервер реально пришлёт корректное содержимое. Поэтому на границе приложения могут понадобиться runtime-проверки.

Не путайте. JSON - формат сериализации данных. База данных - система хранения. API - контракт обмена. Это три разных понятия.
Урок 1 • Раздел 9

9. HTML: каркас страницы

HTML отвечает за структуру. В хорошем интерфейсе элементы выбираются не только по внешнему виду, но и по смыслу. Заголовки, формы, кнопки, списки и навигация имеют семантику.

<main>
  <h1>Мои задачи</h1>

  <form>
    <label>
      Название задачи
      <input type="text" name="title">
    </label>
    <button type="submit">Добавить</button>
  </form>

  <ul>
    <li>Изучить HTTP</li>
    <li>Создать Angular-проект</li>
  </ul>
</main>
Контекст. Это скелет экрана «Мои задачи» в TaskFlow: заголовок, форма добавления и список.
Аналогия из жизни. HTML — как каркас дома: стены и перегородки (теги) говорят, где что находится. Сами по себе они не красят и не «оживляют» дом — за это отвечают CSS и JS.
Разбор по шагам:
  1. <main> — главная область страницы.
  2. <form> с <input> — поле, куда пользователь впишет название новой задачи.
  3. <ul> / <li> — ненумерованный список задач.
Что увидит пользователь: заголовок «Мои задачи», поле ввода с кнопкой «Добавить» и два пункта списка.

Семантический HTML полезен для доступности, сопровождения и понимания кода. Framework не заменяет HTML; он помогает программатически управлять им.

В дальнейшем Angular template или React JSX будут выглядеть похожими на HTML, но это не обычный статический документ: они связаны с данными и компонентами.

Урок 1 • Раздел 10

10. CSS: представление без бизнес-логики

CSS управляет внешним видом, расположением, адаптивностью и состояниями представления. В TaskFlow задача completed может оставаться тем же объектом данных, а CSS-класс отвечает за визуальное оформление завершённой задачи.

.task {
  padding: 12px;
  border: 1px solid #ddd;
}

.task.completed {
  text-decoration: line-through;
  opacity: 0.65;
}
Контекст. В TaskFlow выполненная задача получает класс completed, и CSS делает её «тусклой» и перечёркнутой.
Аналогия из жизни. CSS — как обои и краска в доме. Каркас (HTML) один и тот же, а покрасить комнату можно по-разному, не перестраивая стены.
Разбор по шагам:
  1. .task — стиль для каждой задачи: отступ и рамка.
  2. .task.completed — стиль только для выполненных: перечёркивание и полупрозрачность.
Что увидит пользователь: готовая задача выглядит серой и зачёркнутой, хотя данные в ней не изменились.

Это простой пример разделения ответственности. Если сервер меняет completed с false на true, бизнес-состояние меняется в данных. UI получает новый результат и применяет соответствующее оформление.

В рамках курса отдельно будем изучать flexbox, grid, responsive design и компонентные стили. На первом занятии достаточно увидеть границу: CSS описывает визуальное поведение, а не бизнес-правила вроде «кто имеет право удалить задачу».

Урок 1 • Раздел 11

11. JavaScript: поведение и события

JavaScript даёт странице поведение. Он может читать ввод, реагировать на click, отправлять запрос, считать данные и менять состояние. Именно JavaScript делает веб-приложение программой.

const tasks = []; // массив задач — наше состояние

// Функция-действие: добавляет новую задачу в состояние
function addTask(title) {
  tasks.push({
    id: tasks.length + 1, // простой автоинкремент id
    title,                // название пришло из аргумента
    completed: false      // новая задача ещё не выполнена
  });
}

addTask('Изучить JavaScript'); // вызов меняет состояние
Контекст. Здесь мы вручную, на чистом JavaScript, добавляем задачу в список — ровно то, что позже сделает компонент в Angular/React.
Аналогия из жизни. Функция addTask — как кассир, который берёт название задачи, выдаёт ей номерок (id) и кладёт в общую стопку.
Разбор по шагам:
  1. Создаём пустой массив tasks.
  2. При вызове addTask('Изучить JavaScript') в массив добавляется объект с новым id, названием и флагом completed: false.
  3. После вызова в tasks лежит одна задача.
Что увидит пользователь: пока ничего на экране (вывод не реализован) — но в «памяти» программы задача появилась.

С появлением десятков компонентов ручное управление DOM становится сложнее. Нужно помнить, какой элемент обновить, какие классы убрать, какие счётчики пересчитать. Framework решает проблему не потому, что JavaScript плох, а потому, что крупному приложению нужна организованная модель управления UI.

Главная мысль. Angular и React не заменяют JavaScript. Они предлагают архитектурную модель разработки интерфейса на JavaScript/TypeScript.
Урок 1 • Раздел 12

12. DOM и почему декларативный UI удобен

DOM представляет документ в памяти браузера. JavaScript может напрямую изменять его. Для небольшого примера это нормально. Для большого приложения ручная синхронизация DOM и состояния становится источником ошибок.

Предположим, в списке сто задач. Пользователь завершил одну. Мы должны обновить checkbox, класс, счётчик, возможно, положение элемента после фильтрации и содержимое панели статистики. Если каждый кусок UI обновляется отдельно, появляется риск рассинхронизации.

Декларативная модель говорит иначе: вот текущее состояние данных, вот правила отображения. Framework сам применяет необходимые изменения. React строит UI из компонентов и состояния; Angular использует templates и реактивную модель. В обоих случаях мы двигаемся от «какой DOM-элемент поменять» к «какое состояние должно быть».

▶️ Быстрый запуск. Аналог на чистом JS/HTML: браузер строит DOM-список из массива данных. Angular и React делают то же, но на основе состояния и компонентов (запуск через ng serve / npm run dev).
Контекст. В TaskFlow список задач на экране строится из массива данных. Ниже — тот же принцип на чистом JS, без фреймворка.
Аналогия из жизни. DOM — это скелет/дерево страницы, как родословное дерево: есть ствол (body), от него ветки (div, ul), а на ветках листики (li). JS «приклеивает» к веткам нужный текст.
Песочница: нажми «Запустить» — и увидишь список задач, собранный браузером прямо из массива данных. Меняй код и запускай снова.
Песочница: DOM из данных (аналог на JS)
State-driven UIStateданныеRenderUI из данныхEventдействие пользователяUpdateновое состояние
Рисунок 2. State-driven UI: интерфейс является представлением состояния.
Урок 1 • Раздел 13

13. TypeScript: типы как внутренний контракт

TypeScript расширяет JavaScript системой типов. Для frontend это особенно важно, потому что одна сущность может пройти длинный путь: API → service → state → component → template. Если форма объекта меняется, типы помогают обнаружить часть мест, требующих изменения.

// Модель данных задачи — контракт полей и типов
interface Task {
  id: number;        // уникальный идентификатор
  title: string;     // текст задачи
  completed: boolean; // выполнена или нет
}

// Чистая функция: возвращает НОВЫЙ объект вместо изменения старого
function toggleTask(task: Task): Task {
  return {
    ...task,                  // копируем все поля
    completed: !task.completed // инвертируем только флаг
  };
}

Но типы не проверяют содержимое внешнего HTTP-ответа во время выполнения. Если сервер прислал completed как строку, TypeScript сам по себе не остановит сетевой ответ. Поэтому типизация и runtime validation дополняют друг друга.

В дальнейшем TypeScript станет общей основой и Angular, и React-части курса.

Урок 1 • Раздел 14

14. Promise, async/await и реальное время сети

Сетевой запрос не завершается мгновенно. Код должен уметь ждать результат и обрабатывать ошибку. Promise представляет будущее значение или причину отказа операции.

Откуда вообще берётся /api/tasks?

Очень важный момент для новичка: выражение fetch('/api/tasks') не создаёт API. Оно только отправляет HTTP-запрос по указанному адресу. Поэтому прежде чем использовать такой пример, нам нужно поднять сервер, который действительно отвечает на этот запрос.

В учебных упражнениях мы используем локальный mock API. Это небольшой сервер, который имитирует backend и хранит тестовые данные в JSON-файле.

Важно. Убедитесь, что json-server запущен в отдельной папке taskflow-api, а не внутри Angular-проекта или React-проекта. Иначе порт может конфликтовать или клиент не найдёт mock-данные.
Почему mock API? Мы можем изучать frontend и HTTP, не создавая полноценный backend с авторизацией и базой данных. Позже тот же frontend можно подключить к настоящему API.

Создаём mock API через JSON Server

Создайте отдельную папку для API и откройте в ней терминал:

mkdir taskflow-api
cd taskflow-api
npm init -y
npm install json-server
Контекст. Готовим отдельную папку taskflow-api — учебный «сервер» для TaskFlow, чтобы не трогать основной проект.
Аналогия из жизни. npm install — как покупка нужного инвентаря в хозяйственном магазине: сказали «дай json-server», и он появился в вашем наборе инструментов.

✍️ Действие. Создайте файл taskflow-api/db.json со стартовыми данными задач (содержимое — в блоке ниже).

Создайте файл db.json:

{
  "tasks": [
    {
      "id": 1,
      "title": "Изучить HTTP",
      "completed": false
    },
    {
      "id": 2,
      "title": "Создать первый компонент",
      "completed": false
    }
  ]
}
Контекст. Стартовые данные TaskFlow для mock-сервера: две задачи в формате JSON.
Аналогия из жизни. db.json — как тетрадь с начальным списком дел, которую «сервер» читает вслух, когда его спрашивают.

Запустите mock API:

npx json-server db.json --port 3000
Контекст. Запуск учебного «поддельного» сервера для TaskFlow, который отдаёт задачи из файла db.json.
Аналогия из жизни. JSON Server — как тренажёр кассы в магазине: настоящий кассир не нужен, но «пробивать чеки» можно. Frontend учится общаться с API, не дожидаясь реального бэкенда.

После запуска откройте в браузере http://localhost:3000/tasks. Вы должны увидеть JSON-массив задач. Теперь у нас действительно существует endpoint, к которому frontend может обратиться.

Запрос из JavaScript

// async — функция возвращает Promise; await «ждёт» ответа
async function loadTasks() {
  const response =
    await fetch('http://localhost:3000/tasks'); // запрос к mock API

  // Явно проверяем HTTP-статус, не только успех сети
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  // Парсим тело ответа из JSON в обычный объект JS
  return await response.json();
}
Контекст. Функция, которую TaskFlow вызывает при старте, чтобы забрать задачи из mock API.
Аналогия из жизни. Promise — как обещание + ожидание посылки: вы пообещали получить данные, и код выглядит синхронным, но на деле ждёт ответа. await — это «подожди, пока посылку не привезут». Пока ждём, программа не виснет.
Разбор по шагам:
  1. await fetch(...) отправляет запрос и ждёт ответа.
  2. response.ok — проверяем, что сервер ответил успешно (не 404/500).
  3. Если нет — выбрасываем ошибку.
  4. response.json() превращает текст ответа в удобный JS-объект.

В интерфейсе нужно учитывать состояние ожидания. Кнопка может быть временно отключена, пользователь должен видеть прогресс, а при ошибке - понятное сообщение и возможность повторить операцию. Поэтому работа с API - это не только одна строка fetch, а целый пользовательский сценарий.

Запомните. Любая асинхронная операция имеет как минимум успешный и ошибочный исход. Для UI почти всегда нужен ещё и промежуточный loading-state.
▶️ Быстрый запуск. Аналог на чистом JS: запрос к публичному API httpbin.org и вывод полученного JSON. В курсе тот же принцип используется с mock API на localhost:3000.
Контекст. В TaskFlow при открытии страницы мы загружаем задачи с сервера. Ниже — упрощённый пример загрузки данных по сети из публичного API.
Аналогия из жизни. fetch — как курьер, который везёт заказ: вы отправляете fetch (курьер едет за данными), ждёте посылку (.then), распаковываете её (JSON), а если курьер упал по дороге — ловите ошибку (.catch).
Песочница: нажми «Запустить» — и увидишь JSON, полученный по сети из публичного API. Меняй код и запускай снова.
Песочница: fetch JSON (аналог на JS)
Урок 1 • Раздел 15

15. Frontend и backend: разные ответственности

Frontend отвечает за взаимодействие пользователя с системой: экран, ввод, локальное состояние, навигацию, отображение ошибок. Backend отвечает за операции, которым доверять клиенту нельзя: авторизацию, бизнес-правила, доступ к базе, проверку полномочий и согласованность данных.

Например, кнопка удаления может быть скрыта в интерфейсе для обычного пользователя, но это не защита. Backend должен проверить права независимо от того, каким был интерфейс.

Частая ошибка. «Я скрыл кнопку удаления для обычных пользователей» — это не защита. Любой пользователь может отправить DELETE-запрос через DevTools или curl. Безопасность проверяется на сервере.
# Anyone can send this request regardless of UI
curl -X DELETE http://localhost:3000/tasks/42

# Server must verify permissions
if (!user.hasPermission('delete')) {
  return res.status(403).json({ error: 'Denied' });
}
Контекст. В TaskFlow удалить задачу может не каждый. Код показывает, почему нельзя полагаться только на кнопку в интерфейсе.
Аналогия из жизни. Спрятать кнопку «Удалить» — это как убрать ручку с двери, но оставить замок открытым: хулиган всё равно откроет с улицы. Настоящая защита — проверка на сервере (охрана у входа).
Разбор по шагам:
  1. curl — способ отправить HTTP-запрос вручную, минуя браузер.
  2. Сервер проверяет hasPermission('delete').
  3. Если прав нет — возвращает код 403 (доступ запрещён).
Путь от пользователя до данныхПользовательдействие, ввод,переходБраузерHTML, CSS, JS/TS, UIAPIHTTP-запросы и ответыBackendбизнес-правила ибезопасностьDatabaseдолговременноесостояние
Рисунок 3. Упрощённые границы frontend, API, backend и database.
Безопасность. Всё, что отправлено в браузер, потенциально видно пользователю. Секретные credentials и критические правила не должны зависеть только от клиентского кода.
Урок 1 • Раздел 16

16. SPA, MPA и зачем нужен клиентский роутинг

MPA означает многостраничную модель: переход может приводить к получению нового HTML-документа. SPA строит основную оболочку приложения на клиенте и меняет экран внутри неё. Оба подхода имеют право на существование.

SPA особенно удобна для приложений, где пользователь много времени проводит внутри интерфейса: CRM, админка, редактор, система задач. MPA может быть проще и эффективнее для некоторых сайтов с преимущественно независимыми страницами.

Важно: Angular и React не означают автоматически «только SPA». Современные инструменты поддерживают разные стратегии рендеринга. Поэтому архитектура выбирается под продукт, а не под название framework.

Пример определения маршрута

// Angular
// Angular: массив маршрутов — URL сопоставляется с компонентом
const routes: Routes = [
  { path: 'tasks', component: TaskListPage },       // /tasks -> список
  { path: 'tasks/:id', component: TaskDetailPage }  // :id — параметр
];

// React (React Router) — тот же принцип, но в JSX
<Route path="/tasks" element={<TaskListPage />} />
<Route path="/tasks/:id" element={<TaskDetailPage />} />
Контекст. В TaskFlow адрес /tasks открывает список задач, а /tasks/5 — одну задачу с номером 5. Роутинг сопоставляет адрес и экран.
Аналогия из жизни. Роутинг — как табличка на дверях офиса: по номеру комнаты (/tasks) вас провожают в нужный кабинет, не перестраивая здание.
Разбор по шагам:
  1. Angular хранит маршруты в массиве routes.
  2. React делает то же в JSX-тегах <Route>.
  3. :id — переменная часть адреса (номер задачи).

В обоих случаях Framework сопоставляет URL с нужным компонентом и отображает его. Студенту не нужно вручную загружать страницу при каждом переходе — клиентский роутинг перехватывает навигацию и обновляет только необходимую часть экрана.

Урок 1 • Раздел 17

17. CSR, SSR, SSG и hydration

CSR - Client-Side Rendering: HTML-интерфейс в значительной степени строится в браузере. SSR - Server-Side Rendering: сервер формирует HTML для запроса. SSG или prerendering - HTML формируется заранее. Hydration - процесс, при котором клиент подключает интерактивность к уже полученной HTML-разметке.

ПодходГде строится HTMLКогдаИнструмент
CSRВ браузереПосле загрузки JSAngular, React (по умолчанию)
SSRНа сервереПри каждом запросеAngular Universal, Next.js
SSGНа сервереПри сборкеAstro, Next.js (getStaticProps)
Кто формирует HTML?CSRбраузерSSRсерверSSGзаранееHydrationклиент подключаетинтерактивность
Рисунок 4. Четыре связанных понятия рендеринга.

Современный frontend часто смешивает стратегии. Маркетинговая страница может быть prerendered, публичный каталог - SSR, а личный кабинет - client-heavy. Такой подход сложнее, но позволяет подбирать стратегию под требования страницы.

Для курса. Мы сначала освоим обычный компонентный UI, затем вернёмся к SSR/SSG, чтобы студент уже понимал, какую часть работы они изменяют.
Урок 1 • Раздел 18

18. Framework и library: как сравнивать Angular и React

Слова framework и library полезно рассматривать как описание степени ответственности инструмента. Angular предоставляет полноценную платформу: официальный CLI, компоненты, DI, routing, forms и HTTP-инструменты входят в общую экосистему Angular. React сосредоточен на UI-компонентах и опирается на широкую экосистему для маршрутизации, данных и других задач.

Это не делает React слабее и Angular сильнее. Разница означает разные уровни свободы. В Angular больше решений стандартизировано. В React разработчик чаще выбирает инструменты и архитектуру сам.

Framework vs LibraryAngular (Framework)Компоненты + TemplateМаршрутизация (Router)Формы (Forms)HTTP-клиентDI + СервисыCLI + СборкаТестированиеВсё встроено, решения «из коробки»React (Library)Компоненты + JSXReact Router (библиотека)React Hook Form (библиотека)fetch / Axios (библиотека)Context + HooksVite / CRA (библиотека)Vitest / Jest (библиотека)Ядро — UI. Остальное — экосистема
Компонентное дерево приложенияAppоболочка приложенияTaskListсписок задачTaskItemодна задачаTaskFormформаFilterBarфильтр
Рисунок 5. В обоих подходах приложение собирается из компонентов, но окружающая инфраструктура различается.
Правильная постановка вопроса. Не «что лучше?», а «какие ограничения и преимущества даёт выбранный подход именно для нашего продукта?»
Урок 1 • Раздел 19

19. Angular 2026: современная точка отсчёта

В актуальном Angular компоненты по умолчанию являются standalone. Официальная документация прямо указывает, что standalone components можно импортировать напрямую в другие standalone components, а старые компоненты могут использовать NgModule-ориентированный подход. Это означает, что новый курс не должен начинаться с обязательного AppModule.

Angular CLI предназначен для создания, разработки, тестирования, сборки и сопровождения приложений. В актуальной команде ng new standalone включён по умолчанию; strict mode также включён по умолчанию. Актуальная CLI-документация показывает Vitest как стандартный test runner для новых проектов.

npm install -g @angular/cli
ng new task-flow-angular
cd task-flow-angular
ng serve --open
Контекст. Команда создаёт каркас приложения TaskFlow на Angular и запускает его в браузере.
Аналогия из жизни. ng new — как заказ готового набора конструктора: коробка уже с инструментами и инструкцией, осталось только собирать детали.
✍️ Действие. Сгенерируйте проект Angular в папке task-flow-angular/, выполнив команды из блока ниже в терминале.

Это важное обновление относительно старого учебного материала, который был приложен к курсу: старые подходы можно знать для чтения legacy-проектов, но не стоит делать их стартовой моделью обучения.

Урок 1 • Раздел 20

20. Angular component: первый взгляд

💡 Что такое компонент на самом деле? Компонент — это связка из трёх частей: данные (состояние), логика (методы класса/функции) и представление (template/JSX). Вместо одного гигантского файла интерфейс собирается из небольших независимых кусочков, каждый из которых отвечает за свою часть экрана.

Официальный Angular описывает component как основной строительный блок приложения. У компонента есть TypeScript-класс, декоратор @Component, template и selector; у standalone-компонента также есть imports, содержащий зависимости шаблона.

import { Component } from '@angular/core'; // декоратор компонента

@Component({
  selector: 'app-task-page', // тег, по которому компонент вставляется в шаблон
  template: `
    <!-- Заголовок страницы -->
    <h1>TaskFlow</h1>
    <!-- Приветственный текст -->
    <p>Мои задачи</p>
  `
})
export class TaskPage {} // класс хранит логику и данные компонента
Аналогия из жизни. Компонент — как деталь конструктора Lego: у неё есть своя форма (template), свои «настройки» (данные) и она умеет что-то делать (логика). Из многих таких деталей собирают целую модель — интерфейс TaskFlow.
Разбор по шагам:
  1. @Component — «бирка», которая говорит Angular: это компонент.
  2. selector: 'app-task-page' — имя тега, как <app-task-page></app-task-page>, чтобы вставить компонент в страницу.
  3. template — что показывать (заголовок и текст).
  4. export class TaskPage — «мозг» компонента, где позже появятся данные и методы.

Здесь класс содержит логику и данные, template описывает представление, selector определяет использование компонента, а decorator сообщает Angular, как этот класс должен обрабатываться.

В следующих занятиях мы научимся разделять такие компоненты, передавать данные, обрабатывать события и подключать сервисы.

Урок 1 • Раздел 21

21. Angular template: данные и события

Template связывает HTML-подобную разметку с данными компонента. Интерполяция {{ title }} показывает значение. Property binding задаёт свойства DOM, event binding реагирует на события. Современный Angular также предоставляет новый control flow syntax, например @if и @for.

<!-- Интерполяция: значение переменной title попадает в текст -->
<h1>{{ title }}</h1>

@if (tasks.length === 0) {
  <!-- Новый control flow Angular: условный блок -->
  <p>Задач пока нет.</p>
}

<!-- Event binding: клик вызывает метод компонента -->
<button (click)="addDemoTask()">
  Добавить пример
</button>
Контекст. Шаблон экрана TaskFlow: заголовок берётся из данных, а кнопка запускает метод компонента.
Аналогия из жизни. Интерполяция {{ title }} — как рамка для фотографии: вы вставляете туда любую картинку (значение), и на стене (экране) показывается именно она. А (click) — как звонок: нажали → сработало действие.
Разбор по шагам:
  1. {{ title }} подставляет значение переменной в заголовок.
  2. @if показывает блок только когда задач нет.
  3. (click)="addDemoTask()" вызывает метод при нажатии.

Важно понимать направление связи. Template может отображать значение, пользователь может вызвать событие, а обработчик меняет состояние компонента. Это отличается от старой модели, где разработчик вручную искал DOM-элемент и менял его.

Сравнение. В React вместо {{ }} используется {expression} в JSX, вместо (click)onClick={handler}, а вместо @if/@for — условные выражения JavaScript и метод .map(). Подробнее — в разделе 22.
Не бойтесь синтаксиса. Вначале символы {{ }}, () и [] кажутся искусственными. После нескольких практик они читаются как обозначение направления связи.
Урок 1 • Раздел 22

22. React 2026: базовая ментальная модель

React строит UI из компонентов. Компонент - JavaScript-функция, которая возвращает JSX. Props передают данные от родителя к ребёнку. State хранит информацию, которую компонент должен помнить между рендерами.

import { useState } from 'react'; // хук состояния

export default function Counter() {
  // count — текущее значение, setCount — функция обновления
  const [count, setCount] = useState(0);

  return (
    <section>
      <p>Создано задач: {count}</p>
      {/* клик увеличивает состояние на 1 */}
      <button onClick={() => setCount(count + 1)}>
        Добавить
      </button>
    </section>
  );
}
Контекст. Счётчик задач в TaskFlow: при каждом нажатии число растёт, и экран тут же обновляется.
Аналогия из жизни. Состояние (state) — как текущий статус заказа в пиццерии: «в работе / готов / ошибка». count хранит текущее значение (как статус заказа), а setCount его меняет. Как только статус меняется, интерфейс показывает обновлённое значение.
Разбор по шагам:
  1. useState(0) создаёт переменную count (начало 0) и функцию setCount для изменения.
  2. {count} выводит число на экран.
  3. При нажатии setCount(count + 1) число увеличивается на 1, и React перерисовывает компонент.
Что увидит пользователь: «Создано задач: 0», после нажатия — «Создано задач: 1» и так далее.

Официальная документация React подчёркивает, что state является локальной «памятью» компонента и хранится отдельно для каждой позиции компонента в дереве. Это важная концепция, которая позже станет основой для обсуждения state management.

Сравнение. Как вы видели в Angular (разделы 20–21), реактивное состояние может выражаться по-разному: Angular использует signal для реактивного значения, React — хук useState. Оба подхода связывают данные с UI.
Урок 1 • Раздел 23

23. React: props и композиция

Props позволяют сделать компонент переиспользуемым. Вместо жёстко заданной задачи TaskItem получает title и completed от родителя.

// Дочерний компонент получает данные через props
function TaskItem({ title, completed }) {
  return (
    <li>
      {completed ? '✓' : '○'} {title}
    </li>
  );
}

// Родительский компонент: хранит список и композирует детей
export default function TaskList() {
  const tasks = [
    { id: 1, title: 'Изучить HTTP', completed: true },
    { id: 2, title: 'Изучить React', completed: false }
  ];

  return (
    <ul>
      {/* .map превращает данные в компоненты; key нужен React для повторного использования */}
      {tasks.map(task => (
        <TaskItem key={task.id} {...task} />
      ))}
    </ul>
  );
}
Контекст. В TaskFlow список задач собирается из одинаковых «кирпичиков» TaskItem — каждый показывает одну задачу.
Аналогия из жизни. Props — как почтовый ящик ребёнка: родитель опускает туда данные (имя и статус), а TaskItem вынимает их и рисует строку. Сам TaskItem не решает, что показывать — он рисует то, что дали.
Разбор по шагам:
  1. TaskItem получает title и completed через props.
  2. Родитель TaskList хранит массив задач.
  3. tasks.map(...) для каждой задачи создаёт свой <TaskItem>.
  4. key={task.id} помогает React не путать строки при обновлении.

Композиция означает, что большой UI строится из меньших компонентов. React рекомендует разделять компоненты на файлы по мере роста приложения, чтобы код было легче читать и переиспользовать.

Урок 1 • Раздел 24

24. Общее и различное в Angular и React

💡 Зачем виртуальный DOM и чем отличаются подходы? React сравнивает виртуальное описание UI с предыдущим и меняет в реальном DOM только то, что изменилось (дерево — это «виртуальный DOM»). Angular иначе: его механизм обнаружения изменений и signals точечно обновляют привязанные элементы. Обе стратегии решают одну задачу — не перерисовывать весь экран вручную.

На этом этапе полезно сделать паузу и сравнить две технологии без оценки «лучше/хуже». Обе строят UI из компонентов, но дают разные инструменты для представления, state и инфраструктуры.

ЗадачаAngularReact
Компонент@Component + templatefunction + JSX
Данные внизInputs / bindingsProps
СобытиеEvent binding / outputsevent handlers / callbacks
Реактивное состояниеSignals и другие APIuseState и другие Hooks
HTTPHttpClient и экосистема Angularfetch и выбранные библиотеки
RoutingAngular RouterReact Router (библиотека)
FormsReactive Forms / template-basedcontrolled inputs и библиотеки
Архитектураболее стандартизированабольше выбора

Мы вернёмся к этой таблице после каждого большого блока курса и будем сравнивать реальные решения на одном TaskFlow.

Важно. Ни одна технология не лучше другой по умолчанию. Выбор зависит от проекта, команды и требований. Angular даёт больше «из коробки», React — больше гибкости в выборе библиотек.
Урок 1 • Раздел 25

25. Node.js, npm и package.json

Node.js нужен не потому, что браузер не умеет JavaScript, а потому, что инструменты разработки должны работать за пределами браузера. Angular CLI, тестовые средства, сборщики и множество утилит запускаются в Node.js.

npm управляет пакетами и скриптами проекта. В package.json хранятся scripts и зависимости. package-lock.json фиксирует дерево конкретных версий зависимостей. Для студента важно уметь читать эти файлы, но не нужно заучивать каждое поле.

node --version
npm --version

npm install
npm run build
npm test
Контекст. Стандартные команды любого проекта TaskFlow: проверить версию, установить библиотеки, собрать и протестировать.
Аналогия из жизни. npm install — закупка деталей, npm run build — сборка изделия, npm test — проверка на брак перед выдачей.
Практическое правило. Всегда различайте код приложения и инструменты, которые его собирают, проверяют и запускают. Это две связанные, но разные части проекта.
Урок 1 • Раздел 26

26. Git: минимальный рабочий цикл

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

git status
git diff
git add .
git commit -m "Первый экран TaskFlow"
git log --oneline
Контекст. В TaskFlow мы сохраняем каждый шаг (добавили список, починили ошибку) в Git, чтобы не потерять работу.
Аналогия из жизни. Git — как папка с версиями документа: «черновик», «исправлено», «финал». commit — это точка сохранения, к которой можно вернуться.
Частые ошибки: 1) не добавляйте node_modules в коммит — убедитесь, что .gitignore существует (Angular CLI создаёт его автоматически); 2) перед git add . выполните git status и убедитесь, что вы коммитите только нужные файлы.

Хороший commit - это не архив всех действий за неделю, а осмысленная точка. Например, «Добавлен список задач» лучше, чем «fix» или «сделал». В профессиональной разработке Git связан с code review и CI/CD.

Урок 1 • Раздел 27

27. DevTools: Console и Network как обязательные инструменты

Хороший frontend-разработчик не только пишет код, но и умеет наблюдать за его выполнением. В Console можно увидеть runtime-ошибку и stack trace. В Network можно увидеть запрос, его URL, метод, статус, заголовки, тело и время выполнения.

Если API вернул 404, не нужно начинать менять HTML. Если запрос вернул 500, нужно проверить сервер. Если запрос 200, но интерфейс пустой, вероятны проблемы с форматом ответа, обработкой данных или рендерингом.

Такая классификация ошибок постепенно превращает отладку из угадывания в последовательный процесс.

Проверить DNS-разрешение можно командой:

nslookup taskflow.example
Контекст. Проверка, что имя taskflow.example превращается в реальный IP-адрес — первый шаг при диагностике «сайт не открывается».
Аналогия из жизни. DNS — как телефонная книга: вы знаете имя «TaskFlow», а книга подсказывает нужный номер (IP). Если в книге нет записи — вы не дозвонитесь, хотя сам телефон исправен.

Если команда вернёт IP-адрес — домен разрешается. Если ошибка — проблема в DNS, а не в приложении.

Алгоритм. 1) Воспроизвести ошибку → 2) определить уровень → 3) посмотреть фактические данные → 4) сформулировать гипотезу → 5) проверить одну гипотезу.
Урок 1 • Раздел 28

28. Accessibility: интерфейс должен быть понятен не только мыши

Доступность начинается с семантики. Кнопка должна быть button, поле - input с понятной подписью, изображение - с подходящим alt, структура заголовков - логичной. Framework не отменяет эти требования.

Почему это относится к архитектуре? Потому что хороший component должен иметь не только внешний вид, но и правильное поведение. Если компонент использует div вместо кнопки только ради стиля, клавиатурная навигация и доступность могут пострадать.

Неправильно

<div class="btn" onclick="save()">Сохранить</div>

Правильно

<button type="button" (click)="save()">Сохранить</button>
Ключевые правила a11y: 1) Используйте семантические теги (<button>, <nav>, <main>); 2) Добавляйте alt к изображениям; 3) Обеспечивайте навигацию с клавиатуры (Tab, Enter, Escape).

В дальнейших уроках мы будем учитывать accessibility при создании форм, диалогов, таблиц и навигации.

Урок 1 • Раздел 29

29. Безопасность: границы доверия

Всё, что выполняется в браузере, находится под контролем пользователя. Поэтому frontend не является доверенной зоной. Скрытие кнопки, disabled-состояние или проверка роли в компоненте не являются заменой серверной авторизации.

Например, если пользователь не должен удалять задачи другого пользователя, backend обязан проверить право на DELETE-запрос. Даже если кнопка удаления не отображается в UI, запрос можно сформировать вручную.

Это фундаментальная архитектурная идея: удобство пользователя обеспечивается frontend, а безопасность - сервером и инфраструктурой.

Урок 1 • Раздел 30

30. Производительность: что влияет на скорость

Производительность frontend зависит не от одного фактора. Важны сетевой RTT, размер JavaScript, изображения, количество запросов, порядок загрузки, серверное время и стратегия рендеринга. Поэтому утверждение «SPA быстрее» слишком общее.

На практике разработчик измеряет, а не угадывает. Lighthouse, DevTools Performance, Network и Web Vitals помогают понять, что увидит и почувствует пользователь.

В TaskFlow мы сначала построим правильную архитектуру, а затем научимся измерять. Оптимизация до измерения часто приводит к усложнению кода без реального эффекта.

Урок 1 • Раздел 31

31. State: минимальное состояние и производные данные

Состояние должно содержать минимальный набор самостоятельных фактов. Если количество завершённых задач можно вычислить из массива tasks, отдельный completedCount обычно не нужен. Иначе два источника истины могут разойтись.

React официально рекомендует избегать redundant state. Та же логика полезна и в Angular: вычисляемое значение лучше получать из источника, чем хранить отдельно без необходимости.

const completedTasks = tasks.filter(task => task.completed);
const completedCount = completedTasks.length;

Этот принцип станет особенно важным при изучении signals, computed, selectors и state management.

Урок 1 • Раздел 32

32. Local state и server state

Не вся информация в приложении одинаковая. Local state может описывать открытие диалога или выбранную вкладку. Server state - данные, пришедшие от API и потенциально изменяющиеся вне текущего компонента.

Server state сложнее: его нужно загружать, кэшировать, обновлять, инвалидировать и обрабатывать при ошибках. Поэтому библиотеки для запросов и state management решают задачи, которые не сводятся к простому useState или одной переменной.

// Local state — локальное состояние UI
const [isOpen, setIsOpen] = useState(false);
// Оно живёт только в этом компоненте

// Server state — данные с сервера
const [tasks, setTasks] = useState([]);
  useEffect(() => {
    // Загрузка server state при монтировании компонента
    fetch('/api/tasks')
      .then(res => res.json())
      .then(data => setTasks(data)); // кладём ответ в состояние
  }, []); // пустой массив — эффект выполняется один раз
// Эти данные могут измениться на сервере
// независимо от действий пользователя
Контекст. В TaskFlow «открыт ли фильтр» — это local state, а сам список задач приходит с сервера (server state).
Аналогия из жизни. Local state — ваши заметки на липком листке (видны только вам). Server state — доска объявлений в кабинете: её мог поправить кто-то другой, пока вы отвернулись.
Разбор по шагам:
  1. isOpen — локальная «галочка» открытого диалога, живёт в компоненте.
  2. tasks — данные с сервера.
  3. useEffect с пустым массивом загружает задачи один раз при старте.
  4. Пришедшие данные кладутся в setTasks.

В Angular и React мы разберём эту границу отдельно, потому что она существенно влияет на архитектуру приложения.

Урок 1 • Раздел 33

33. Loading, empty, error — четыре состояния UI

Базовых состояния три: loading, success, error. Но success делится на два подтипа: с данными и с пустым списком. Пустой список и незагруженный список - разные состояния. Во время запроса приложение ещё не знает результат. Если запрос завершился и сервер вернул [], это уже успешное, но пустое состояние.

СостояниеЧто знает приложениеЧто показывает UI
LoadingОтвет ещё не полученИндикатор загрузки
Success + dataДанные полученыСписок
Success + emptyДанные получены, список пустСообщение «пока нет задач»
ErrorЗапрос не завершился успешноОшибка + повторить

Если эти состояния смешать, пользователь будет видеть «ничего» и не понимать, идёт ли загрузка или система сломалась. Это одна из самых частых ошибок первых frontend-приложений.

Урок 1 • Раздел 34

34. Как проектировать TaskFlow до кода

Перед написанием компонента полезно описать сценарий пользователя. Например: пользователь открывает /tasks, видит список, нажимает «Добавить», вводит название, сохраняет, получает новую задачу и видит её в списке.

Из сценария выводятся UI-компоненты, состояния и API-вызовы. Не наоборот. Это важный метод проектирования: сначала поведение продукта, затем техническая реализация.

Сценарий: создание задачи

1. Открыть форму
2. Ввести title
3. Нажать «Создать»
4. Показать loading
5. POST /api/tasks
6. Обработать успех или ошибку
7. Обновить список
8. Показать результат
Контекст. Это «сценарий создания задачи» в TaskFlow — каркас, по которому мы пишем код в следующих уроках.
Аналогия из жизни. Сценарий — как рецепт приготовления блюда: сначала достань продукты, потом готовь, потом подай. Если пропустить шаг «показать загрузку», пользователь решит, что кнопка сломалась.
Идея курса. Каждый последующий урок будет брать один такой сценарий и реализовывать его сначала на Angular, затем в React.
Урок 1 • Раздел 35

35. Практика: подготовка окружения

Перед практикой проверьте Node.js, npm и Git. Установите VS Code или другой удобный редактор. Angular CLI можно установить глобально через npm согласно официальной документации.

node --version
npm --version
git --version

npm install -g @angular/cli
ng version
Контекст. Перед стартом TaskFlow проверяем, что Node.js, npm и Git установлены, а Angular CLI доступна.
Аналогия из жизни. Это как проверка инструментов перед ремонтом: убедиться, что есть молоток (Node), гвозди (npm) и инструкция (CLI), прежде чем забивать первый гвоздь.

На этом шаге не нужно изучать все флаги CLI. Важно увидеть, что команды выполняются, версии выводятся и среда готова.

Если команда не найдена, не перескакивайте сразу к случайным решениям из поисковой выдачи: проверьте PATH, версию Node.js и способ установки. Для учебной группы лучше заранее использовать одну согласованную LTS-версию Node.js.

Какие версии нужны. Angular 22 требует Node.js 20+ (рекомендуется LTS 22.x). Проверьте: node --version должен показать v20 или v22. Если версия старше — обновите Node.js с официального сайта.
EACCES ошибка при npm install -g. Если терминал выдаёт «EACCES permission denied», не используйте sudo. Вместо этого установите Node.js через nvm (Node Version Manager) или переустановите Node.js с правами администратора.
ng version не выводит версию? Убедитесь, что путь к npm global bin добавлен в PATH. На Windows это обычно %APPDATA%\npm. Перезапустите терминал после установки.
Урок 1 • Раздел 36

36. Практика: первый локальный Angular-проект

Создайте проект TaskFlow. Современный Angular CLI использует standalone API по умолчанию. Это важно: проект, который вы увидите, будет отличаться от приложенного старого материала, где центральное место занимает AppModule.

ng new task-flow-angular
cd task-flow-angular
ng serve --open

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

Что проверить. Студент должен понимать не только команду, но и путь: файл изменился → CLI пересобрал → browser получил обновлённый bundle → template отобразился.
Где править. Стартовый шаблон Angular находится в файле src/app/app.html. Это HTML-похожий файл со стилями и SVG-логотипом. Замените его содержимое на простой текст:
<h1>TaskFlow</h1>
<p>Приложение для управления задачами</p>

Сохраните файл. Angular CLI отслеживает изменения и автоматически пересобирает приложение. Обновление страницы в браузере не требуется — hot reload подставит новый контент.

Если страница пустая. Проверьте, что файл сохранён и терминал не показывает ошибок. Частая причина — синтаксическая ошибка в шаблоне (например, незакрытый тег). Исправьте ошибку и сохраните снова.
Урок 1 • Раздел 37

37. Практика: первый компонент списка задач

Создайте отдельный компонент для списка задач. В современном Angular standalone component можно использовать напрямую из другого standalone component. CLI создаёт его как самостоятельную единицу.

ng generate component task-list
Контекст. Команда создаёт отдельный кирпич TaskFlow — компонент списка задач.
Аналогия из жизни. ng generate — как пресс-форма: назвали деталь «task-list», и вам выдали готовую заготовку с нужными отверстиями.

Добавьте в шаблон три задачи. Не усложняйте упражнение API, сервисами и маршрутизацией. Цель - почувствовать компонентную границу и увидеть, что экран можно собирать из нескольких частей.

<h2>Мои задачи</h2>
<ul>
  <li>Изучить HTTP</li>
  <li>Создать компонент</li>
  <li>Подготовить TaskFlow</li>
</ul>
Контекст. Разметка компонента TaskList: простой список из трёх задач-заглушек.
Аналогия из жизни. Это как наклейки на дверь холодильника: три записи, которые пока никуда не подключены, но уже видны.
Подсказка. Файлы компонента находятся в src/app/task-list/. Файл task-list.ts содержит класс и декоратор, task-list.html — шаблон. Не редактируйте app.ts и app.html на этом шаге — вернёмся к ним позже.
Урок 1 • Раздел 37.1

37.1. Практика: подключение компонента к корню

Компонент TaskList создан, но он существует отдельно — его никто не использует. Чтобы он появился на экране, нужно подключить его к корневому компоненту App. В Angular 22 это делается за три шага.

Шаг 1. Импорт в классе компонента

Откройте src/app/app.ts. В Angular 22 standalone-компоненты подключаются через массив imports в декораторе @Component — точно так же, как подключается RouterOutlet. Добавьте импорт класса TaskList и укажите его в массиве:

import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { TaskList } from './task-list/task-list';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet, TaskList],
  templateUrl: './app.html',
  styleUrl: './app.css'
})
export class App {
  protected readonly title = signal('task-flow-angular');
}
Контекст. Корневой компонент TaskFlow «приглашает» дочерний TaskList внутрь себя.
Аналогия из жизни. imports — как список гостей на вечеринке: пока TaskList не в списке, его не пустят в дом (а значит, тег <app-task-list> не сработает).

Обратите внимание: путь './task-list/task-list' указывает на файл task-list.ts внутри папки task-list/. Расширение .ts указывать не нужно — TypeScript разберётся сам.

Важно. Если вы не добавите TaskList в imports, Angular не узнает селектор <app-task-list> и выдаст ошибку в консоли браузера: «'app-task-list' is not a known element».

Шаг 2. Использование селектора в шаблоне

Теперь, когда TaskList импортирован, его селектор <app-task-list> становится доступен в шаблоне. Откройте src/app/app.html и полностью замените его содержимое на:

<div class="app-container">
  <h1>TaskFlow</h1>
  <app-task-list />
</div>

<router-outlet />
Контекст. Шаблон корня TaskFlow: заголовок плюс вставленный список задач.
Аналогия из жизни. Тег <app-task-list /> — как розетка: вы вставляете в неё готовый прибор (компонент), и он начинает работать в этом месте страницы.

Строка <app-task-list /> — это само-закрывающийся тег. Angular видит его, находит соответствующий компонент в imports и вставляет шаблон task-list.html прямо в это место. На экране вы увидите заголовок «TaskFlow» и список задач.

Частая ошибка. Студенты часто не удаляют шаблон-заглушку Angular (с логотипом и ссылками на документацию). Это не ошибка — страница просто будет выглядеть перегруженной. Если вы хотите чистый старт, удалите всё содержимое app.html и замените на код выше.

Шаг 3. Базовые стили

Откройте src/app/app.css и добавьте стили:

:host {
  display: block;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
}

.app-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 2rem 1rem;
}

h1 {
  text-align: center;
  color: #333;
  margin-bottom: 2rem;
}
Контекст. Базовые стили страницы TaskFlow: ширина, отступы и центрирование заголовка.
Аналогия из жизни. :host — как покраска самого дома снаружи: правило применяется к зданию целиком, а не к отдельной комнате.

Свойство :host стилизует сам корневой элемент <app-root>. Без него display: block не сработает, потому что по умолчанию Angular-компонент — инлайновый.

Итог: что изменилось и зачем

ФайлЧто сделаноЗачем
app.tsДобавлен импорт TaskList в importsСообщить Angular, что корневой компонент знает про TaskList
app.htmlЗаменён шаблон, добавлен <app-task-list />Вставить содержимое task-list.html в разметку главной страницы
app.cssДобавлены стили контейнераОформление страницы: шрифт, центрирование, отступы

Почему это работает

В Angular standalone-компоненты — это автономные единицы. Каждый имеет свой селектор, шаблон и стили. Чтобы использовать один компонент внутри другого, достаточно:

  1. Импортировать класс компонента в imports массив
  2. Использовать его селектор в шаблоне как обычный HTML-тег

Не нужен NgModule, не нужно регистрировать компоненты в модулях — всё работает напрямую. Это одно из ключевых отличий Angular 22 от предыдущих версий.

Проверка

Запустите приложение и убедитесь, что всё работает:

npm start
Контекст. Запуск готового проекта TaskFlow на Angular, чтобы увидеть результат всех предыдущих шагов.
Аналогия из жизни. npm start — как нажать «вкл» на собранном приборе: всё, что мы собирали, оживает и открывается в браузере.

Откройте http://localhost:4200. На экране вы должны увидеть заголовок TaskFlow и список из трёх задач под ним. Если компонент не появился — проверьте консоль браузера на наличие ошибок компиляции.

Алгоритм при ошибке. 1) Посмотрите терминал — есть ли ошибки компиляции? 2) Откройте Console в DevTools — есть ли runtime-ошибки? 3) Проверьте, что файлы app.ts, app.html и task-list/task-list.ts сохранены.
Урок 1 • Раздел 38

38. Практика: первый React-компонент

В отличие от предыдущего фрагмента, здесь мы не предполагаем, что React уже установлен. Сначала создадим полноценный проект. Для учебного курса используем Vite и шаблон React + TypeScript.

Шаг 1. Создаём проект

npm create vite@latest taskflow-react -- --template react-ts
cd taskflow-react
npm install
npm run dev
Контекст. Создаём проект TaskFlow на React через Vite — современный «пульт управления» проектом.
Аналогия из жизни. npm create vite — как выбор пустого трейлера под ваши нужды: вы сказали «хочу React + TypeScript», и вам собрали базу, которую осталось наполнить.

После npm run dev Vite покажет локальный адрес, обычно вида http://localhost:5173. Откройте его в браузере. Теперь у нас есть настоящий React-проект, а не изолированный пример кода.

Шаг 2. Где находится наш код

В типичном проекте Vite основная точка приложения находится в src. Файл App.tsx содержит корневой компонент, а main.tsx запускает React-приложение в браузере.

Шаг 3. Создаём компонент TaskList

Замените содержимое src/App.tsx на:

type Task = {
  id: number;
  title: string;
  completed: boolean;
};

const tasks: Task[] = [
  { id: 1, title: 'Изучить HTTP', completed: false },
  { id: 2, title: 'Создать UI', completed: false },
  { id: 3, title: 'Изучить React', completed: false }
];

function TaskList() {
  return (
    <ul>
      {tasks.map(task => (
        <li key={task.id}>
          {task.title}
        </li>
      ))}
    </ul>
  );
}

export default function App() {
  return (
    <main>
      <h1>TaskFlow</h1>
      <TaskList />
    </main>
  );
}
Контекст. Это первый реальный React-компонент TaskFlow: заголовок и список задач, собранный из данных.
Аналогия из жизни. map() — как конвейер на заводе: на входе лежит список деталей (задач), на выходе — готовые коробки (<li>). Одна деталь → один элемент списка.
Разбор по шагам:
  1. Тип Task описывает форму задачи.
  2. tasks — готовый список из трёх задач.
  3. TaskList через map() превращает каждую задачу в строку списка.
  4. App собирает заголовок и список вместе.

Здесь студент видит несколько важных идей одновременно: React-компонент является функцией, JSX находится внутри TypeScript-кода, массив можно обрабатывать обычным JavaScript методом map(), а key нужен для стабильной идентификации элементов списка.

Необходимый результат. После этого шага на странице должны появиться заголовок TaskFlow и три задачи. Если этого не произошло, прежде чем менять код компонента, проверьте терминал Vite и Console в DevTools.
Урок 1 • Раздел 39

39. Практика: сравнить одну и ту же задачу

Возьмём простой сценарий: отобразить название задачи и кнопку. В Angular шаблон использует Angular syntax, а в React JSX использует JavaScript-выражения и props.

Angular
<h3>{{ task.title }}</h3>
<button (click)="toggleTask()">
  Изменить статус
</button>
React
<h3>{task.title}</h3>
<button onClick={toggleTask}>
  Изменить статус
  </button>
Контекст. Одна и та же кнопка «Изменить статус» в TaskFlow: слева — как пишут в Angular, справа — как в React.
Аналогия из жизни. Это как два пульта одной телевизора: кнопки называются по-разному ((click) против onClick), но обе нажимают «переключить канал».

Смысл почти одинаковый: показать данные и связать действие с обработчиком. Синтаксис отличается, а ментальная модель похожа. Именно такие параллели будут основой второй половины курса.

Урок 1 • Раздел 40

40. Практика: сделать состояние видимым

Теперь переведём идею состояния из теории в работающий код. Сначала сделаем это в React, потому что здесь хорошо видно разделение между текущим значением и функцией его изменения.

import { useState } from 'react';

export default function TaskStatus() {
  const [completed, setCompleted] = useState(false);

  return (
    <section>
      <p>
        Статус: {completed ? 'Готово' : 'В работе'}
      </p>

      <button onClick={() => setCompleted(!completed)}>
        Изменить статус
      </button>
    </section>
  );
}
Контекст. Кнопка «Изменить статус» задачи в TaskFlow: нажали — и слово «В работе» превращается в «Готово».
Аналогия из жизни. Состояние — как текущий статус заказа в пиццерии: «в работе / готов / ошибка». completed — это статус (в работе / готово), а setCompleted его переключает. Как только статус меняется, интерфейс показывает новое слово сам, без вашего участия.
Разбор по шагам:
  1. useState(false) — статус изначально «В работе».
  2. В <p> через ? : выбираем текст в зависимости от completed.
  3. При нажатии setCompleted(!completed) значение переворачивается.
  4. React перерисовывает текст автоматически.
Что увидит пользователь: «Статус: В работе» → после клика → «Статус: Готово».

После клика setCompleted изменяет состояние, React выполняет новый рендер компонента, и текст на странице меняется. Это простой пример state-driven UI: интерфейс зависит от состояния.

Та же идея в Angular

В современном Angular для реактивного локального значения можно использовать signal:

import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-task-status',
  template: `
    <p>Статус: {{ completed() ? 'Готово' : 'В работе' }}</p>

    <button (click)="toggle()">
      Изменить статус
    </button>
  `
})
export class TaskStatusComponent {
  completed = signal(false);

  toggle() {
    this.completed.update(value => !value);
  }
}
Контекст. Та же кнопка «Изменить статус», но на Angular с помощью signal — реактивной переменной.
Аналогия из жизни. Signal — как переменная с «громкой связью»: стоит ей измениться, и все, кто на неё смотрит (в шаблоне), тут же узнают об этом, как подписчики в мессенджере узнают о новом сообщении.
Разбор по шагам:
  1. signal(false) — реактивное значение «не готово».
  2. completed() (со скобками!) читает значение в шаблоне.
  3. toggle() через update() переворачивает значение.

Здесь completed() читает значение signal, а update() изменяет его. В следующем Angular-блоке курса мы разберём signals подробнее, включая computed() и связь с template.

Цель упражнения. Не запомнить два синтаксиса, а увидеть одну общую идею: пользовательское действие меняет состояние, а UI отображает новое состояние.
Урок 1 • Раздел 41

41. Как пользоваться самостоятельной работой и подсказками

Самостоятельная работа в этом пособии построена по принципу «сначала попытка, затем проверка». Не открывайте ответы сразу: сначала попробуйте решить задачу самостоятельно, используя код и схемы из урока.

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

После выполнения задания сравните своё решение с кратким ответом в конце. Совпадение строк кода не является целью. Важно, чтобы совпадала логика и результат.

Императивный подход

// Находим элемент и меняем вручную
const li = document.querySelector('#task-1');
li.style.textDecoration = 'line-through';
li.classList.add('completed');
document.querySelector('#counter').textContent = count;
Контекст. В TaskFlow «вручную» так обновляли бы список и счётчик до появления фреймворков.
Аналогия из жизни. Императивный подход — как самому бежать переставлять таблички: «возьми эту, зачеркни ту, обнови счётчик». Работает, но легко ошибиться, если табличек много.

Декларативный подход

<!-- Описываем результат при данном состоянии -->
<li [class.completed]="task.completed">
  {{ task.title }}
</li>
  <span>Выполнено: {{ completedCount() }}</span>
Контекст. Тот же результат в TaskFlow, но на языке фреймворка: мы говорим «задача выполнена — покажи её зачёркнутой», а не «перечеркни вручную».
Аналогия из жизни. Декларативный подход — как сказать дизайнеру: «сделай так, чтобы выполненные задачи были серыми». Вы описали что нужно, а он сам решает, как перекрасить. Меньше шансов ошибиться.

Во втором случае мы описываем что должно быть, а Framework применяет изменения к DOM самостоятельно.

Правило обучения. Если решение отличается от ответа, но работает, понятно читается и соблюдает условия задания, такое решение может быть правильным.
Урок 1 • Раздел 42

42. Самопроверка: связать всё в одну систему

Попробуйте устно объяснить следующую историю. Пользователь вводит адрес TaskFlow. Браузер разбирает URL, получает сетевую информацию, устанавливает HTTPS-соединение и делает HTTP-запрос. Сервер отвечает HTML и/или данными. JavaScript/TypeScript формирует интерактивный UI. Пользователь нажимает «Создать». Frontend формирует запрос к API. Backend проверяет данные и права, сохраняет новую запись и возвращает ответ. UI обновляет state и показывает новую задачу.

Если вы можете объяснить эту цепочку без подсказок, то основная цель занятия достигнута. Angular и React на следующем уровне помогут организовать клиентскую часть этой цепочки.

Путь от пользователя до данныхПользовательдействие, ввод,переходБраузерHTML, CSS, JS/TS, UIAPIHTTP-запросы и ответыBackendбизнес-правила ибезопасностьDatabaseдолговременноесостояние
Рисунок 6. Целостная модель, которую нужно унести с первого занятия.
Урок 1 • Раздел 43

43. Что будет на следующих занятиях Angular

После этой базы мы перейдём к Angular практически. Сначала - компоненты и templates. Затем - data binding (связь данных с шаблоном), события, conditional rendering (условный рендеринг), списки, inputs/outputs (передача данных между компонентами), lifecycle (этапы жизни компонента от создания до уничтожения), services (сервисы для бизнес-логики) и dependency injection (механизм предоставления зависимостей компоненту). После этого появятся forms, HTTP, routing, signals и state.

Каждая тема будет привязана к TaskFlow. Например, forms - это создание задачи, HTTP - получение и сохранение задач, routing - экран списка и экран отдельной задачи, signals - реактивное состояние фильтров и списка.

Такой порядок позволяет не изучать API изолированно. Каждый новый механизм появляется как решение конкретной задачи продукта.

Урок 1 • Раздел 44

44. Что будет на следующих занятиях React

После Angular мы построим React-версию TaskFlow. Сначала компоненты и JSX, затем props, state, события, списки и формы. Затем Hooks (механизмы React для state и побочных эффектов), Context (— способ передачи данных компонентам без props), производительность и тестирование, производительность и тестирование.

Особое внимание будет уделено не копированию Angular-модели, а пониманию React mental model. Например, state в React локален компоненту, а его организация зависит от места компонента в дереве. Официальная документация отдельно подчёркивает принципы выбора структуры state и избегания избыточных данных.

В конце мы сможем реализовать одинаковые сценарии TaskFlow двумя подходами и предметно сравнить решения.

Урок 1 • Раздел 45

45. Домашнее задание

Задание 1. Нарисуйте архитектуру TaskFlow от пользователя до базы данных и подпишите ответственность каждого уровня.

Задание 2. Создайте JSON с пятью задачами. Для каждой используйте id, title, completed и createdAt.

Задание 3. Создайте небольшой HTML/JS-прототип списка задач с добавлением новой записи.

Задание 4. Создайте и запустите Angular-проект task-flow-angular.

Задание 5. Сравните Angular и React в восьми предложениях: что общего, а что различается по архитектуре.

Готовность. Перед следующим занятием проект должен запускаться локально без ошибок.
Урок 1 • Раздел 46

46. Контрольные вопросы

1. Что делает браузер? (раздел 3) 2. Что такое URL? (раздел 4) 3. Зачем нужен DNS? (раздел 5) 4. Что содержит HTTP-запрос? (раздел 6) 5. Что означает статус 404? (раздел 6) 6. Что такое API? (раздел 7) 7. Чем JSON отличается от базы данных? (раздел 8) 8. Для чего нужен TypeScript? (раздел 13) 9. Почему компонент является удобной единицей архитектуры? (разделы 20, 22) 10. Что такое state? (разделы 31, 32) 11. Что такое SPA? (раздел 16) 12. Чем CSR отличается от SSR? (раздел 17) 13. Почему frontend не является доверенной зоной? (разделы 15, 29) 14. Зачем нужен Node.js? (раздел 25) 15. Для чего нужен npm? (раздел 25) 16. Почему нужен Git? (раздел 26) 17. Что общего у Angular и React? (разделы 18, 24) 18. Чем отличается их экосистемный подход? (раздел 18) 19. Почему не стоит дублировать derived state? (раздел 31) 20. Что нужно проверить в Network при ошибке API? (раздел 27)

Урок 1 • Проверка самостоятельной работы

Ответы и подсказки к заданиям

Этот раздел нужен для самостоятельной сверки. Сначала выполните работу без подсказок. Затем проверьте идею решения.

Домашнее задание 1 — архитектура

Подсказка: нарисуйте не инструменты, а ответственность уровней.

Пользователь
  ↓
Браузер / Angular / React
  ↓
HTTP API
  ↓
Backend
  ↓
Database

Ожидаемая идея: frontend отвечает за UI и клиентское взаимодействие, backend — за серверные правила и доступ к данным, database — за долговременное хранение.

Домашнее задание 2 — JSON

Минимальный пример:

{
  "id": 1,
  "title": "Изучить HTTP",
  "completed": false,
  "createdAt": "2026-08-17"
}

Остальные четыре записи должны иметь другие id.

Домашнее задание 3 — HTML/JS

Подсказка: заведите массив задач, найдите ul и после добавления заново сформируйте список.

Главная проверка: после клика появляется новая запись, а не просто сообщение в Console.

Домашнее задание 4 — Angular

Минимум: выполнить ng new task-flow-angular, перейти в каталог, выполнить ng serve --open и изменить стартовый template.

Домашнее задание 5 — Angular vs React

Проверяйте смысл, а не формулировку: обе технологии компонентные; Angular предлагает более встроенную платформу, React концентрируется на UI и оставляет больше инфраструктурных решений экосистеме.

Упражнение с mock API

Если fetch('http://localhost:3000/tasks') возвращает ошибку, проверьте три вещи:

  1. запущен ли JSON Server;
  2. правильно ли указан порт 3000;
  3. существует ли endpoint /tasks в db.json.
Урок 1 • Раздел 47

47. Мини-словарь

ТерминОпределение
BrowserСреда, которая загружает и выполняет веб-код.
DOMОбъектное представление документа в браузере.
HTTPПротокол веб-обмена сообщениями.
URLАдрес ресурса.
APIКонтракт взаимодействия между программами.
JSONФормат структурированных данных.
FrontendКлиентская часть приложения.
BackendСерверная часть приложения.
ComponentПереиспользуемый строительный блок UI.
StateДанные, определяющие текущее состояние интерфейса.
CSRФормирование UI преимущественно на клиенте.
SSRФормирование HTML на сервере.
SSGПредварительное формирование HTML.
FrameworkИнструмент/платформа, задающая значительную часть структуры приложения.
LibraryПереиспользуемый код, который приложение вызывает по необходимости.
TypeScriptЯзык с типовой системой поверх JavaScript.
Node.jsСреда выполнения JavaScript вне браузера.
npmМенеджер пакетов и скриптов.
GitСистема контроля версий.
PromiseОбъект, представляющий будущий результат асинхронной операции.
async/awaitСинтаксис для удобной работы с Promise внутри асинхронных функций.
PropsВходные данные React-компонента, переданные родителем.
HookСпециальная React-функция для использования state и других возможностей внутри функционального компонента.
SignalРеактивное значение Angular, изменение которого может отслеживаться системой реактивности.
DIDependency Injection: получение зависимости из внешнего механизма создания зависимостей.
HydrationПодключение клиентской интерактивности к HTML, который уже был сформирован сервером.
Mock APIУчебная имитация backend API, обычно используемая для разработки frontend без настоящего сервера.
ViteИнструмент разработки и сборки frontend-проектов; в курсе используется для создания React-приложения.
JSXСинтаксис, позволяющий описывать UI-структуру внутри JavaScript/TypeScript-кода React-компонента.
KeyСтабильный идентификатор элемента списка, который React использует для сопоставления элементов между обновлениями.
EndpointКонкретный адрес API, по которому клиент может выполнить определённую операцию.
RuntimeСреда, в которой фактически выполняется программа.
Урок 1 • Раздел 48

48. Источники и актуализация материала

Этот курс ориентируется на современный workflow и поэтому ссылки должны использоваться как часть обучения, а не только как список литературы.

Angular. Для создания проекта используйте официальную документацию Installation и ng new. В актуальном CLI standalone API включён по умолчанию, а ng serve --open запускает локальный development server.

Angular standalone. Angular рекомендует использовать standalone components вместо NgModule для нового кода. Это особенно важно как противопоставление старому приложенному учебному материалу, где центральное место занимал AppModule.

React и Vite. Для React в этом курсе используется шаблон react-ts через Vite. Официальный Vite предоставляет шаблоны react и react-ts.

Примечание о версиях. Команды CLI и tooling развиваются. Если студент проходит курс спустя значительное время после его публикации, сначала нужно сверить команды с официальной документацией, а уже затем сравнивать результат с текстом пособия.

Урок 1 • Практический справочник

48A. Если что-то не запускается: алгоритм диагностики

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

  1. Команда не найдена. Проверьте, установлен ли Node.js и попал ли путь к программе в PATH.
  2. Angular не запускается. Выполните ng version и затем ng serve без дополнительных флагов, чтобы увидеть полное сообщение.
  3. React/Vite не запускается. Проверьте npm install, затем npm run dev.
  4. fetch возвращает Failed to fetch. Проверьте, запущен ли mock API и доступен ли http://localhost:3000/tasks.
  5. 404. Проверьте URL и существование endpoint.
  6. 500. Проверьте серверную часть или mock API; frontend может быть исправен.
  7. В Console ошибка TypeScript/JavaScript. Читайте первую полезную строку stack trace и смотрите файл/строку.
Правило. Сначала наблюдение, затем гипотеза, затем одно изменение. Не меняйте пять файлов одновременно.
Урок 1 • Раздел 49

49. Практическая лаборатория: от клика до HTTP

Выполните упражнение без framework. Создайте кнопку «Загрузить задачи». При нажатии выведите в Console сообщение, затем выполните GET-запрос к тестовому endpoint. Проследите запрос во вкладке Network и сравните данные в Response с тем, что выводится в Console.

async function load() {
  console.log('Начинаем загрузку');
  const response = await fetch('/api/tasks');
  const data = await response.json();
  console.log('Получено:', data);
}

Главная цель лаборатории - увидеть полный цикл: событие пользователя → JavaScript → HTTP → response → данные. Если backend ещё не подготовлен, используйте локальный mock или любой согласованный учебный endpoint.

Пример
Урок 1 • Раздел 50

50. Практическая лаборатория: три состояния UI

Создайте простой компонент, который различает loading, success и error. На старте покажите кнопку. После нажатия установите loading. Если запрос успешен, покажите список. Если произошла ошибка, покажите сообщение и кнопку повторной попытки.

Это упражнение кажется простым, но оно вводит важную идею state machine. Интерфейс не просто «есть» или «нет». Он находится в одном из нескольких состояний, а переходы между ними вызываются событиями и результатами операций.

idle -> loading -> success
                 -> error -> loading
Контекст. Схема переходов между состояниями экрана загрузки задач в TaskFlow.
Аналогия из жизни. Это как три состояния посылки: в пути (loading) → доставлена (success), а если помеха — «потеряна (error) → попробуй снова». Главное — нельзя быть в двух состояниях сразу.

Стартовый код (React)

import { useState } from 'react';

export default function TaskLoader() {
  const [status, setStatus] = useState('idle');
  const [tasks, setTasks] = useState([]);
  const [error, setError] = useState(null);

  // TODO: реализуйте handleLoad
  // 1) setStatus('loading')
  // 2) fetch tasks
  // 3) setStatus('success') или setStatus('error')

  return (
    <div>
      {status === 'idle' && <button onClick={handleLoad}>Загрузить</button>}
      {status === 'loading' && <p>Загрузка...</p>}
      {status === 'error' && <p>Ошибка: {error}</p>}
      {status === 'success' && (
        <ul>{tasks.map(t => <li key={t.id}>{t.title}</li>)}</ul>
      )}
    </div>
  );
}
Контекст. Заготовка экрана TaskFlow, который умеет показывать три состояния: «пусто», «загрузка», «ошибка/успех».
Аналогия из жизни. Состояния UI — как три состояния посылки: в пути (грузим), доставлена (показали список), потеряна (ошибка, попробуй ещё). Нельзя одновременно показывать «гружу» и «готово» — это запутает пользователя.
Пример
Урок 1 • Раздел 51

51. Практическая лаборатория: минимальная модель Task

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

interface Task {
  id: number;
  title: string;
  completed: boolean;
  createdAt: string;
}

interface TaskForm {
  title: string;
}
Контекст. Форма задачи в TaskFlow: какие поля обязательны, а какие сервер добавит сам.
Аналогия из жизни. Тип (interface) — как анкета: в ней написано, какие графы заполнять. TaskForm — это черновик (нужно только имя), а Task — готовая запись, куда сервер добавил номер и дату.

Разделение Task и TaskForm полезно: форма создания не обязана знать id и createdAt до отправки на сервер. Такой маленький пример показывает, почему типы помогают моделировать границы данных.

Пример
Урок 1 • Раздел 52

52. Практическая лаборатория: компонентное дерево

Нарисуйте дерево TaskFlow и распределите ответственность: AppShell, Header, Sidebar, TaskPage, TaskList, TaskItem, TaskForm, FilterBar. Для каждого компонента запишите две вещи: какие данные ему нужны и какие события он может инициировать.

AppShell:  данные=__, события=__
Header:    данные=__, события=__
Sidebar:   данные=__, события=__
TaskPage:  данные=__, события=__
TaskList:  данные=__, события=__
TaskItem:  данные=__, события=__
TaskForm:  данные=__, события=__
FilterBar: данные=__, события=__
Контекст. Каркас экранов TaskFlow: кто какие данные получает и какие действия запускает.
Аналогия из жизни. Компонентное дерево — как матрёшка или оргштатная структура фирмы: директор (AppShell) делегирует отделам (Header, TaskList), а те — конкретным сотрудникам (TaskItem). Каждый знает только свою задачу.

Заполните шаблон, опираясь на код из предыдущих разделов. Не существует единственного правильного ответа — важно уметь обосновать свой выбор.

Framework vs LibraryAngular (Framework)Компоненты + TemplateМаршрутизация (Router)Формы (Forms)HTTP-клиентDI + СервисыCLI + СборкаТестированиеВсё встроено, решения «из коробки»React (Library)Компоненты + JSXReact Router (библиотека)React Hook Form (библиотека)fetch / Axios (библиотека)Context + HooksVite / CRA (библиотека)Vitest / Jest (библиотека)Ядро — UI. Остальное — экосистема
Используйте эту схему как отправную точку, а затем измените её под собственный вариант TaskFlow.

Если два компонента начинают постоянно обмениваться большим числом данных, подумайте, не находится ли их общее состояние слишком низко или слишком высоко. Это станет центральной темой при изучении state architecture.

Пример
Урок 1 • Раздел 53

53. Практическая лаборатория: сравнение Angular и React без копирования кода

Возьмите одну задачу: «Показать список задач и кнопку изменения статуса». Сначала опишите поведение словами: данные приходят в компонент; UI показывает title и completed; click вызывает действие; state меняется; UI обновляется.

После этого отдельно реализуйте её на Angular и React. Не переносите синтаксис напрямую. Сначала сформулируйте архитектуру, затем выберите соответствующий механизм каждой технологии.

ШагAngularReact
Получить данныеcomponent/service/APIcomponent/API или hook
Передать данныеinput/bindingprops
Событиеevent binding/outputcallback/event handler
Изменить состояниеsignal/service и др.setState/reducer и др.
ОтобразитьtemplateJSX
Результат. Если вы умеете объяснить каждый шаг словами до написания кода, переход между frameworks становится намного легче.
Пример
Урок 1 • Раздел 54

54. Финальная страница урока: что должно остаться в голове

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

На следующем занятии мы перестанем говорить о framework в общих терминах и начнём строить Angular-приложение как систему компонентов. С этого момента каждая теория будет сразу превращаться в код и часть TaskFlow.

Источники

Angular — Components

Angular CLI

Angular ng new

React — State

React — Managing State

React — Components

Node.js Downloads

Актуальность технических сведений проверена 17 августа 2026 года. При выпуске нового учебного потока версии Node.js, Angular CLI и другого tooling следует сверить с официальной документацией.

Куда дальше: разбираем компоненты и шаблоны в Уроке 3, а дерево компонентов — в лабораторной №4.

📖 Глоссарий

ТерминЖизненная аналогияКоротко
AngularКонструктор с подробной инструкцией: взял коробку — и собирай по шагамПолноценный фреймворк для веб-приложений (компоненты, маршруты, формы)
ReactНабор качественных инструментов, из которых ты сам строишь свой наборБиблиотека для создания интерфейсов из компонентов (ядро — только UI)
КомпонентДеталь конструктора или запчасть машины: маленькая, понятная, соединяется с другимиНезависимый кусочек интерфейса с данными и поведением
ФреймворкКонструктор с инструкцией: он говорит, где что лежит и в каком порядке собиратьКаркас приложения, задающий правила и структуру
БиблиотекаНабор инструментов в ящике: берёшь нужное, остальное решаешь самНабор готовых функций, которые вызываешь по своему усмотрению
Шаблон (template)Чертёж детали: на нём помечено, куда вставить надписи и кнопкиРазметка компонента, связанная с его данными
Дерево компонентовМатрёшка: большая фигура внутри содержит всё меньшие и меньшиеВложенность компонентов: один содержит другие

🧠 Самопроверка

1. Angular и React — это одно и то же, просто разные названия одной библиотеки. Верно или неверно?

2. Компонент — это целое готовое приложение, которое нельзя разбить на части. Верно или неверно?

3. Шаблон компонента похож на чертёж, куда подставляются данные. Верно или неверно?

Прогресс курса