项目实例:待办事项应用(To-Do List)
目标:创建一个功能完整的待办事项应用,用户可以添加任务、标记完成、删除任务,并且数据保存在本地存储中。
项目功能
- 添加任务
- 标记任务为完成
- 删除任务
- 数据持久化(localStorage)
- 实时更新界面
项目目录结构
todo-app/
├── index.html
├── styles.css
└── script.js
1. index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do List App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>To-Do List</h1>
<div class="input-group">
<input type="text" id="taskInput" placeholder="Enter a new task..." />
<button id="addTaskBtn">Add Task</button>
</div>
<ul id="taskList"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
2. styles.css
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
width: 400px;
}
h1 {
text-align: center;
color: #333;
}
.input-group {
display: flex;
margin-bottom: 20px;
}
input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 10px;
background-color: #28a745;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #218838;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
margin-bottom: 10px;
background-color: #f9f9f9;
border: 1px solid #ccc;
border-radius: 4px;
}
li.completed {
text-decoration: line-through;
color: #888;
}
button.delete-btn {
background-color: #dc3545;
color: white;
border: none;
border-radius: 4px;
padding: 5px;
cursor: pointer;
}
button.delete-btn:hover {
background-color: #c82333;
}
3. script.js
// DOM Elements
const taskInput = document.getElementById('taskInput');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskList = document.getElementById('taskList');
// Load tasks from localStorage
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
// Render tasks to the DOM
function renderTasks() {
taskList.innerHTML = ''; // Clear existing tasks
tasks.forEach((task, index) => {
const li = document.createElement('li');
li.className = task.completed ? 'completed' : '';
li.innerHTML = `
${task.text}
<div>
<button onclick="toggleTask(${index})" class="toggle-btn">${task.completed ? 'Undo' : 'Complete'}</button>
<button onclick="deleteTask(${index})" class="delete-btn">Delete</button>
</div>
`;
taskList.appendChild(li);
});
}
// Add a new task
function addTask() {
const taskText = taskInput.value.trim();
if (taskText) {
tasks.push({ text: taskText, completed: false });
taskInput.value = '';
saveTasks();
renderTasks();
}
}
// Toggle task completion
function toggleTask(index) {
tasks[index].completed = !tasks[index].completed;
saveTasks();
renderTasks();
}
// Delete a task
function deleteTask(index) {
tasks.splice(index, 1);
saveTasks();
renderTasks();
}
// Save tasks to localStorage
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Event Listeners
addTaskBtn.addEventListener('click', addTask);
taskInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addTask();
}
});
// Initial render
renderTasks();
功能实现
- 任务添加:点击“Add Task”或按 Enter 键,输入框内容被保存为任务。
- 任务完成状态切换:点击任务旁的“Complete”按钮,切换为“Undo”,并标记任务已完成。
- 任务删除:点击“Delete”按钮,删除任务。
- 数据持久化:任务列表实时存储到
localStorage,刷新页面后任务仍然存在。
测试用例
用例 1:添加任务
- 输入框中输入 "Learn JavaScript"。
- 点击 "Add Task" 按钮。
- 检查任务是否正确显示。
用例 2:标记任务完成
- 点击任务旁的 "Complete" 按钮。
- 检查任务是否加上删除线。
用例 3:删除任务
- 点击任务旁的 "Delete" 按钮。
- 检查任务是否从列表中移除。
用例 4:数据持久化
- 添加几个任务并完成部分任务。
- 刷新页面,确保任务状态正确恢复。
项目运行截图
-
初始页面:
- 显示空任务列表。
-
添加任务后:
- 每个任务显示“Complete”和“Delete”按钮。
-
任务完成后:
- 文本加删除线,按钮显示“Undo”。
-
删除任务:
- 从界面中移除。