TODO-App Musterlösung (Vue.js)
Dies ist die vollständige Musterlösung für die TODO-App mit Vue.js.
Verwendung
- Kopiere den gesamten Code unten
- Erstelle eine neue HTML-Datei (z.B.
todo-app-vue.html) - Füge den Code ein und speichere die Datei
- Öffne die Datei in deinem Browser
Code
html
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO App - Vue.js</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f5f5;
padding: 20px;
}
.container {
max-width: 500px;
margin: 50px auto;
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
font-size: 32px;
}
input[type="text"] {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 16px;
transition: border-color 0.3s, box-shadow 0.3s;
}
input[type="text"]:focus {
outline: none;
border-color: #4CAF50;
box-shadow: 0 0 5px rgba(76, 175, 80, 0.5);
}
button {
width: 100%;
background-color: #4CAF50;
color: white;
font-size: 16px;
padding: 12px;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 15px;
transition: background-color 0.2s;
}
button:hover {
background-color: #45a049;
}
ul {
list-style: none;
padding: 0;
margin-top: 20px;
}
.todo-item {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f9f9f9;
padding: 12px 15px;
margin-bottom: 10px;
border-radius: 5px;
border: 1px solid #ddd;
transition: all 0.3s ease;
}
.todo-item:hover {
transform: translateX(5px);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.todo-item span {
flex: 1;
transition: all 0.3s;
}
.completed {
text-decoration: line-through;
color: #888;
}
.complete-btn,
.delete-btn {
padding: 5px 10px;
border: none;
border-radius: 3px;
cursor: pointer;
margin-left: 5px;
width: auto;
margin-top: 0;
transition: background-color 0.2s;
}
.complete-btn {
background-color: #4CAF50;
color: white;
}
.complete-btn:hover {
background-color: #45a049;
}
.complete-btn:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.delete-btn {
background-color: #f44336;
color: white;
}
.delete-btn:hover {
background-color: #da190b;
}
.empty-message {
text-align: center;
color: #999;
margin-top: 20px;
}
</style>
</head>
<body>
<div id="app" class="container">
<h1>Meine TODO-Liste</h1>
<input
type="text"
v-model="todoInput"
@keyup.enter="addTodo"
placeholder="Neue Aufgabe eingeben...">
<button @click="addTodo">Hinzufügen {{todoInput}}</button>
<p v-if="todos.length === 0" class="empty-message">
Keine Aufgaben vorhanden. Füge eine neue hinzu!
</p>
<ul v-else>
<li v-for="(todo, index) in todos" :key="index" class="todo-item">
<span :class="{ completed: todo.completed }">{{ todo.text }}</span>
<button
class="complete-btn"
@click="completeTodo(index)"
:disabled="todo.completed">
✓
</button>
<button class="delete-btn" @click="deleteTodo(index)">✗</button>
</li>
</ul>
</div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data() {
return {
todoInput: '',
todos: [
{text: "Hallo Welt", completed: false}
]
}
},
methods: {
addTodo() {
// Input-Wert prüfen
if (this.todoInput.trim() === '') {
alert('Bitte Aufgabe eingeben!');
return;
}
// TODO zum Array hinzufügen
this.todos.push(
{
text: this.todoInput,
completed: false
}
);
// Input leeren
this.todoInput = '';
},
deleteTodo(index) {
// TODO aus Array entfernen
this.todos.splice(index, 1);
},
completeTodo(index) {
// TODO als erledigt markieren
this.todos[index].completed = true;
}
}
}).mount('#app')
</script>
</body>
</html>Erklärung
Diese Vue.js Lösung zeigt die wichtigsten Vue-Konzepte:
- Reaktive Daten:
todoInputundtodosArray imdata()Bereich - Two-Way Binding:
v-modelfür automatische Synchronisation zwischen Input und Daten - Event Handling:
@clickund@keyup.enterfür Benutzerinteraktionen - List Rendering:
v-forzum automatischen Rendern der TODO-Liste - Conditional Rendering:
v-ifundv-elsefür die leere Nachrichten-Anzeige - Dynamic Classes:
:classfür das durchgestrichene Styling - Methods: Alle Logik sauber in Methoden organisiert
Vorteile gegenüber Vanilla JavaScript
- Weniger Code: Vue übernimmt die DOM-Manipulation automatisch
- Deklarativ: Du beschreibst, WAS angezeigt werden soll, nicht WIE
- Reaktivität: Änderungen an Daten aktualisieren die UI automatisch
- Bessere Organisation: Daten, Methoden und Template sind klar getrennt