JavaScript

Практические задачи по JavaScript для начинающих: DOM, массивы и события

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

Работайте в одном файле index.html или в связке index.html и script.js. Для каждой задачи сначала добейтесь результата на простых данных, затем добавьте один неудобный случай: пустой ввод, повтор, неизвестный фильтр или отсутствие элементов

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

По этой теме полезно отдельно посмотреть Вопросы JavaScript на собеседовании, чтобы расширить контекст и сравнить подходы

Базовая HTML-разметка для задач

Можно начать с такой страницы и менять блоки под конкретные задания

<input id="taskInput" placeholder="Новая задача">
<button id="addTask">Добавить</button>
<ul id="taskList"></ul>
<p id="message"></p>
<script src="script.js"></script>

Главная идея: JavaScript берет элементы страницы, слушает событие и меняет DOM. Если один из трех шагов пропущен, интерфейс не будет работать

Задача 1. Добавить элемент в список

Пользователь вводит текст и нажимает кнопку. Нужно добавить новый пункт в список

const input = document.querySelector('#taskInput');
const button = document.querySelector('#addTask');
const list = document.querySelector('#taskList');
const message = document.querySelector('#message');

button.addEventListener('click', () => {
  const title = input.value.trim();

  if (!title) {
    message.textContent = 'Введите текст задачи';
    return;
  }

  const item = document.createElement('li');
  item.textContent = title;
  list.append(item);
  input.value = '';
  message.textContent = '';
});

Проверьте пустую строку и строку из пробелов. Без trim() такая задача часто ломается незаметно

Задача 2. Хранить задачи в массиве

Теперь храните данные отдельно от разметки. Это важный шаг: DOM показывает состояние, но источником состояния становится массив

const tasks = [];

function renderTasks() {
  list.innerHTML = '';

  tasks.forEach((task) => {
    const item = document.createElement('li');
    item.textContent = task.title;
    list.append(item);
  });
}

button.addEventListener('click', () => {
  const title = input.value.trim();
  if (!title) return;

  tasks.push({ title, done: false });
  input.value = '';
  renderTasks();
});

Если список на странице стал неправильным, проверьте массив через console.log(tasks). Так проще понять, ошибка в данных или в выводе

Задача 3. Отметить задачу выполненной

Добавьте обработчик клика по пункту списка

function renderTasks() {
  list.innerHTML = '';

  tasks.forEach((task, index) => {
    const item = document.createElement('li');
    item.textContent = task.done ? `✓ ${task.title}` : task.title;

    item.addEventListener('click', () => {
      tasks[index].done = !tasks[index].done;
      renderTasks();
    });

    list.append(item);
  });
}

Эта задача показывает связь массива и DOM: клик меняет данные, затем интерфейс перерисовывается

Задача 4. Фильтр выполненных задач

Добавьте кнопки Все, Активные, Готовые. Храните текущий фильтр в переменной

let filter = 'all';

function getVisibleTasks() {
  if (filter === 'active') {
    return tasks.filter((task) => !task.done);
  }

  if (filter === 'done') {
    return tasks.filter((task) => task.done);
  }

  return tasks;
}

В renderTasks() используйте getVisibleTasks(). Проверьте пустой список, список только из выполненных задач и переключение фильтра после добавления новой задачи

Задача 5. Поиск по списку

Добавьте поле поиска и показывайте только задачи, где есть введенный текст

const searchInput = document.querySelector('#search');
let query = '';

searchInput.addEventListener('input', () => {
  query = searchInput.value.trim().toLowerCase();
  renderTasks();
});

function getVisibleTasks() {
  return tasks.filter((task) => {
    const matchesQuery = task.title.toLowerCase().includes(query);
    const matchesFilter = filter === 'all' || (filter === 'done' ? task.done : !task.done);
    return matchesQuery && matchesFilter;
  });
}

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

Задача 6. Сохранение в localStorage

Чтобы задачи не пропадали после перезагрузки, сохраните массив

function saveTasks() {
  localStorage.setItem('tasks', JSON.stringify(tasks));
}

function loadTasks() {
  const raw = localStorage.getItem('tasks');
  return raw ? JSON.parse(raw) : [];
}

После каждого изменения вызывайте saveTasks(). При загрузке страницы берите начальное значение из loadTasks()

Частые ошибки

Первая ошибка — менять DOM и забывать менять массив. После перерисовки данные пропадают

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

Третья ошибка — хранить всё в innerHTML. Для учебного старта лучше создавать элементы через createElement, потому что так понятнее, где текст, где кнопка, где событие

Четвертая ошибка — не обрабатывать пустое состояние. Пользователь должен видеть «задач нет», а не просто пустой блок

Мини-проект для закрепления

Соберите todo-list с такими функциями:

  • добавить задачу
  • отметить задачу выполненной
  • удалить задачу
  • фильтровать по статусу
  • искать по тексту
  • сохранять в localStorage

Если эта версия работает, вы уже закрыли главные темы начального JavaScript: DOM, события, массивы, объекты, функции и хранение состояния

Задача 7. Удаление задачи

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

function removeTask(id) {
  const index = tasks.findIndex((task) => task.id === id);

  if (index !== -1) {
    tasks.splice(index, 1);
    saveTasks();
    renderTasks();
  }
}

В renderTasks() создайте кнопку, повесьте на нее обработчик и вызовите removeTask(task.id). Проверьте удаление первой, последней и единственной задачи

Задача 8. Счетчик задач

Покажите пользователю, сколько задач осталось выполнить

function getActiveCount() {
  return tasks.filter((task) => !task.done).length;
}

function renderCounter() {
  counter.textContent = `Осталось: ${getActiveCount()}`;
}

Вызывайте renderCounter() после добавления, удаления и переключения задачи. Так вы увидите, что интерфейс зависит от данных, а не живет отдельно

Как проверять весь мини-проект

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

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

Задача 9. Сообщение для пустого списка

Когда задач нет, покажите отдельное сообщение. Это маленькая деталь, но она делает интерфейс понятнее

function renderEmptyState() {
  message.textContent = tasks.length === 0 ? 'Задач пока нет' : '';
}

Вызывайте эту функцию после renderTasks(). Проверьте три случая: список пустой, добавлена одна задача, все задачи удалены

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x