Форма отправляет одно поле (title). Сервер отвечает полным объектом с id, createdAt и completed. Узнайте, почему граница между этими двумя моделями важна.
TaskForm отличается от TaskПрежде чем писать код, разберёмся с главной идеей. Всё строится вокруг понятия модель данных.
Аналогия. Модель данных — это как бланк. У бланка есть графы: «Имя», «Дата», «Номер». Когда вы его заполняете, получается упорядоченная запись, с которой удобно работать. В программе модель данных делает то же самое: задаёт, какие сведения о задаче мы храним и в каком виде.
Аналогия. TaskForm — это как форму заказа: вы пишете только название задачи. Вы не придумываете номер заказа и не ставите время — об этом позаботится сервер. В нашей программе TaskForm содержит только то, что ввёл человек: title (название задачи).
Суть: TaskForm — это минимальный набор полей, который мы отправляем на сервер, чтобы создать задачу.
Аналогия. Task — это готовый билет с `id` и `completed`. В нём уже есть и ваше название (title), и присвоенный номер (id), и время оформления (createdAt), и статус (completed — «выполнено или нет»). Сервер сам добавляет эти поля, потому что только он знает, какой номер свободен и который час.
Суть: Task — это полная запись задачи, которую сформировал сервер и которую мы показываем пользователю и храним в списке.
✍️ Действие. Создайте файл lab3.html (в любой папке, где вам удобно). Это и есть наша маленькая «лаборатория».
Контекст. Ниже — полный готовый файл. В нём есть форма ввода, список задач и чёрное «окошко консоли», куда выводятся два объекта: сначала TaskForm (что отправили), потом Task (что вернул сервер). Это поможет вам воочию увидеть разницу.
Аналогия. Представьте, что вы отправляете только форму заказа (TaskForm), а сервер возвращает готовый билет с `id` и `completed` (Task). Код ниже имитирует именно этот обмен.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Лаборатория 3: Task и TaskForm</title>
<style>
/* --- Оформление страницы (на вид не влияет, только красота) --- */
body { font-family: Arial, sans-serif; max-width: 600px;
margin: 40px auto; padding: 20px; }
.form-area { display: flex; gap: 10px; margin-bottom: 20px; }
.form-area input { flex: 1; padding: 10px; font-size: 15px;
border: 1px solid #d8dee8; border-radius: 6px; }
.form-area button { padding: 10px 20px; font-size: 15px;
background: #159957; color: white;
border: none; border-radius: 6px; cursor: pointer; }
#taskList { list-style: none; padding: 0; }
#taskList li { background: #f8f9fa; padding: 14px; margin-bottom: 8px;
border-radius: 6px; border-left: 4px solid #2d5bff; }
.meta { font-size: 13px; color: #526071; margin-top: 4px; }
/* Чёрное окошко "консоли" — туда мы будем выводить объекты */
#console { background: #0f172a; color: #f8fafc; padding: 16px;
border-radius: 8px; font-family: monospace; font-size: 13px;
margin-top: 20px; white-space: pre-wrap; max-height: 300px;
overflow: auto; }
</style>
</head>
<body>
<h2>Создать задачу</h2>
<div class="form-area">
<!-- Поле ввода: сюда пользователь пишет название задачи -->
<input type="text" id="taskInput" placeholder="Например: Купить молоко">
<!-- Кнопка "Создать": по нажатию запускается весь процесс -->
<button id="addBtn">Создать</button>
</div>
<h3>Список задач</h3>
<ul id="taskList"></ul>
<h3>Консоль (откройте F12 → Console)</h3>
<div id="console">Здесь будут видны два разных объекта...</div>
<script>
// Счётчик для выдачи новых номеров задач (имитация сервера)
let nextId = 1;
var logBox = document.getElementById('console');
// Вывод строки в чёрное окошко консоли
function logToBox(text) {
logBox.textContent += text + '\n';
logBox.scrollTop = logBox.scrollHeight;
}
// Имитация сервера: принимает TaskForm, возвращает Task
// Это как сервер: получил форму заказа, вернул готовый билет с id и completed
function mockServerCreate(formData) {
return new Promise(function(resolve) {
setTimeout(function() {
// Сервер САМ добавляет поля, которых не было в форме
var newTask = {
id: nextId++, // номер заказа (сервер)
title: formData.title, // название (от пользователя)
completed: false, // статус: пока не выполнено
createdAt: new Date().toISOString() // время создания (сервер)
};
resolve(newTask); // "возвращаем готовый билет" обратно в программу
}, 400);
});
}
// Обработчик нажатия кнопки "Создать"
document.getElementById('addBtn').addEventListener('click', async function() {
var input = document.getElementById('taskInput');
var title = input.value.trim();
if (!title) { alert('Введите название задачи!'); return; }
// Шаг 1: создаём TaskForm (только title — то, что ввёл человек)
var formPayload = { title: title };
logToBox('Отправляем (TaskForm): ' + JSON.stringify(formPayload));
// Шаг 2: отправляем "на сервер", получаем полный Task
var createdTask = await mockServerCreate(formPayload);
logToBox('Получили (Task): ' + JSON.stringify(createdTask));
// Шаг 3: рисуем задачу в списке на странице
var li = document.createElement('li');
li.innerHTML = '<div style="font-weight:bold">' + createdTask.title + '</div>'
+ '<div class="meta">ID: ' + createdTask.id
+ ' | Создано: ' + new Date(createdTask.createdAt).toLocaleTimeString()
+ ' | Статус: ' + (createdTask.completed ? 'Выполнено' : 'В ожидании')
+ '</div>';
document.getElementById('taskList').appendChild(li);
input.value = ''; // очищаем поле ввода для следующей задачи
});
</script>
</body>
</html>
Пошаговый разбор того, что происходит при работе кода:
formPayload = { title: ... } — это и есть TaskForm.mockServerCreate «ждёт» 400 миллисекунд (как будто сервер думает) и возвращает уже полный объект Task с добавленными id, createdAt и completed.Что увидит пользователь. Внизу страницы в чёрном окошке появятся две строки, например:
Отправляем (TaskForm): {"title":"Купить молоко"}
Получили (Task): {"id":1,"title":"Купить молоко","completed":false,"createdAt":"2026-08-27T10:00:00.000Z"}
Обратите внимание: во второй строке появились поля, которых не было в первой. Это и есть работа «сервера».
Дважды щёлкните по файлу lab3.html — он откроется в браузере. Введите текст в поле и нажмите «Создать». Чтобы увидеть «настоящую» консоль разработчика, нажмите F12 и откройте вкладку Console.
💡 Попробуйте создать 2–3 задачи подряд и посмотрите, как растёт номер id.
В консоли (и в чёрном окошке) вы видите две строки. Вот их суть в таблице:
| Объект | Поля | Откуда |
|---|---|---|
TaskForm | title | Ввёл пользователь |
Task | id, title, completed, createdAt | Сгенерировал «сервер» |
Аналогия. Как при оформлении заказа: в форме заказа только название, а в готовом билете с `id` и `completed` — ещё и номер, время и статус.
id и createdAt — это ответственность сервера. Разделяя модели, вы избегаете путаницы: что отправляем, а что получаем.Аналогия. Если бы каждый пользователь сам придумывал номер задачи, два человека могли бы выбрать один и тот же — и началась бы каша. Поэтому номер всегда выдаёт сервер. Так же и в коде: пусть сервер сам назначает id и время, а форма (TaskForm) занимается только вводом названия.
💡 Позже, когда будете фильтровать задачи (показывать «только выполненные»), вы будете проверять именно поле completed. А слово done встретится вам как значение фильтра (например, фильтр 'done'), но не как имя поля задачи.
▶️ Посмотрите, как работает преобразование TaskForm → Task прямо здесь:
Контекст. В песочнице ниже тот же принцип, но в упрощённом виде: мы создаём form (это TaskForm) и на его основе собираем task (это Task), добавляя поля, которые «прислал бы сервер».
Аналогия. Как если бы вы взяли форму заказа, вписали туда «Изучить TypeScript», а потом сервер добавил сверху `id` (как номер билета) и дату — вот вам и готовый билет с `id` и `completed`.
TaskForm (только название) и полный Task (с id, временем и статусом). Меняй код и запускай снова.Пошаговый разбор песочницы:
form с одним полем title — это наш TaskForm.task: берём название из формы и добавляем id, completed, createdAt — как будто сервер ответил.Что увидит пользователь. В правой части песочницы появятся два блока: сначала короткий TaskForm (только title), а под ним — полный Task с длинным id, временем и статусом. Нажмите «Запустить» ещё раз — id будет новым каждый раз.
Лаборатория 3 из 5. ← Лаборатория 2 | Лаборатория 4 →
| Термин | Жизненная аналогия | Коротко |
|---|---|---|
TaskForm | Форма заказа / черновик анкеты без номера | Что ввёл пользователь: только title. |
Task | Готовый билет с id и completed | Полная запись от сервера: номер, название, статус, время. |
| Модель данных | Бланк с графами (Имя, Дата, Номер) | Задаёт, какие сведения о задаче мы храним. |
| Сервер | Кассир, выдающий номер билета | Сам добавляет id и createdAt. |
| Валидация | Проверка, не забыли ли заполнить бланк | Убеждаемся, что title не пуст. |
completed | Галочка «выполнено» в билете | Поле задачи: true/false. |
1. В объекте TaskForm уже есть поле id. Верно или неверно?
Ответ: Неверно. TaskForm — это как черновик анкеты без номера: в нём только title. Номер id добавляет сервер, когда выдаёт готовый билет (Task).
2. Поле completed показывает, выполнена задача или нет. Верно или неверно?
Ответ: Верно. completed — это галочка «выполнено» в готовом билете: false, пока задача в ожидании, и true, когда сделана.
3. Слово done — это имя поля задачи. Верно или неверно?
Ответ: Неверно. Имя поля — completed. А done встречается только как значение фильтра (например, фильтр 'done'), то есть «покажи выполненные».