Lista zadań: model w klasie, widok z modelu
Klasy i obiekty - JavaScript od podstaw: konsola (HTML/CSS/JS)
Większy komponent: klasa `TodoList` trzyma model (tablica zadań z polem `done`) i ma metodę `render`, która z modelu odbudowuje listę `<ul>`. Każda akcja użytkownika (dodanie, kliknięcie, usunięcie) zmienia TYLKO model i woła `render`. Dzięki temu widok nigdy nie rozjedzie się z danymi. Kliknięcia obsługuje jeden nasłuchiwacz na liście (delegowanie), a numer zadania niesie atrybut `data-index`.
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Lista zadań</title>
<style>
body { font-family: sans-serif; max-width: 34em; }
.counter { display: inline-flex; gap: 0.5em; align-items: center; border: 1px solid #94a3b8; border-radius: 6px; padding: 0.4em 0.7em; margin: 0.3em; }
.counter .value { min-width: 2em; text-align: center; font-weight: bold; }
button, input { font: inherit; padding: 0.2em 0.6em; }
#list li { cursor: pointer; margin: 0.2em 0; }
#list li.done { text-decoration: line-through; color: #64748b; }
</style>
</head>
<body>
<h1>Do zrobienia</h1>
<input id="new-task" placeholder="Nowe zadanie">
<button id="add">Dodaj</button>
<ul id="list"></ul>
<p id="count"></p>
<script>
class TodoList {
constructor(list, count) {
this.tasks = [];
this.list = list;
this.count = count;
list.addEventListener('click', e => {
const li = e.target.closest('li');
if (!li) return;
const index = Number(li.dataset.index);
if (e.target.matches('.remove')) this.remove(index);
else this.toggle(index);
});
}
add(text) {
if (text.trim() === '') return;
this.tasks.push({ text: text.trim(), done: false });
this.render();
}
toggle(index) {
this.tasks[index].done = !this.tasks[index].done;
this.render();
}
remove(index) {
this.tasks.splice(index, 1);
this.render();
}
render() {
this.list.replaceChildren();
this.tasks.forEach((task, i) => {
const li = document.createElement('li');
li.dataset.index = i;
li.textContent = task.text + ' ';
if (task.done) li.classList.add('done');
const remove = document.createElement('button');
remove.className = 'remove';
remove.textContent = 'usuń';
li.appendChild(remove);
this.list.appendChild(li);
});
const left = this.tasks.filter(t => !t.done).length;
this.count.textContent = `Do zrobienia: ${left} z ${this.tasks.length}`;
}
}
const todo = new TodoList(document.getElementById('list'), document.getElementById('count'));
const field = document.getElementById('new-task');
document.getElementById('add').addEventListener('click', () => {
todo.add(field.value);
field.value = '';
});
todo.add('Odrobić matematykę');
todo.add('Spakować plecak');
todo.toggle(0);
</script>
</body>
</html>Ładowanie interaktywnego edytora... Jeśli się nie pojawi, włącz JavaScript.
Wszystkie lekcje kursu JavaScript od podstaw: konsola·Zaloguj się, aby zapisać postęp na koncie.