1. HTML 结构
- 文档类型声明:
这告诉浏览器这是一个 HTML5 文档。<!DOCTYPE html>
- HTML 标签:
表示整个页面的内容,<html lang="zh-CN">
lang="zh-CN"
表示内容使用简体中文。 - 头部信息:
包含页面的元数据,如字符集、视图窗口设置、标题和样式。<head> <!-- ... --> </head>
- 样式(CSS):
在<style>
标签内定义了页面的样式,包括字体、布局、颜色和响应式设计等。 - 主体内容:
包含网页的所有可见内容。<body> <!-- ... --> </body>
- 容器:
页面内容被包裹在一个容器内,以便于样式控制和布局。<div class="container"> <!-- ... --> </div>
- 标题和输入框:
显示应用的标题和一个输入框供用户输入待办事项。<h1>待办事项列表</h1> <input type="text" id="todoInput" placeholder="请输入待办事项">
- 按钮:
两个按钮分别用于添加新的待办事项和清空所有待办事项。<button class="add-btn" onclick="addTodo()">添加待办</button> <button class="clear-btn" onclick="clearTodos()">清空所有</button>
- 待办事项列表:
待办事项将显示在这个无序列表内。<ul id="todoList"> </ul>
2. JavaScript 行为
- 添加待办事项 (
addTodo
函数):- 获取输入框的值。
- 检查值是否为空。
- 创建一个新的列表项 (
li
)。 - 创建一个删除按钮,并为它绑定点击事件处理函数以从列表中删除对应的待办事项。
- 将待办事项添加到列表中。
- 清空输入框并保存待办事项。
- 清空所有待办事项 (
clearTodos
函数):- 移除列表中的所有子节点。
- 保存待办事项。
- 保存待办事项 (
saveTodos
函数):- 将所有待办事项的文本和完成状态保存到本地存储(
localStorage
)。
- 将所有待办事项的文本和完成状态保存到本地存储(
- 加载待办事项 (
loadTodos
函数):- 从本地存储加载待办事项。
- 为每个待办事项创建列表项和删除按钮,并恢复其完成状态。
- 将待办事项添加到列表中。
- 编辑待办事项(通过双击列表项):
- 弹出对话框让用户编辑待办事项文本。
- 更新列表项的文本并保存待办事项。
- 切换完成状态(通过点击列表项):
- 为列表项添加或移除
completed
类。 - 保存待办事项。
- 为列表项添加或移除
当页面加载时,loadTodos
函数会被调用,从本地存储加载待办事项并显示在页面上。
3. 展示效果
4. 源代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>待办事项列表</title>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
input[type="text"] {
width: 100%; /* 使输入框宽度与容器宽度一致 */
padding: 10px; /* 增加内边距 */
margin-bottom: 10px; /* 添加底部外边距 */
border: 1px solid #ddd; /* 设置边框样式 */
}
button {
padding: 10px; /* 使按钮内边距与输入框一致 */
border: none; /* 移除边框 */
background-color: #4CAF50; /* 设置背景颜色 */
color: white; /* 设置文字颜色 */
cursor: pointer; /* 设置鼠标样式为指针 */
margin-bottom: 10px; /* 添加底部外边距 */
}
button:hover {
background-color: #45a049; /* 鼠标悬停时改变背景颜色 */
}
ul {
list-style: none;
padding: 0;
}
li {
margin: 10px 0;
padding: 10px;
background-color: #f9f9f9;
border: 1px solid #ddd;
position: relative; /* 为待办事项设置相对定位 */
}
.delete-btn {
background-color: #f44336;
color: white;
border: none;
padding: 5px 10px;
cursor: pointer;
position: absolute; /* 为删除按钮设置绝对定位 */
right: 10px; /* 将删除按钮定位到右下角 */
bottom: 10px; /* 将删除按钮定位到右下角 */
width: calc(100% / 6); /* 设置删除按钮宽度为待办框的六分之一 */
}
.completed {
text-decoration: line-through;
color: #aaa;
}
.add-btn {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
margin-top: 20px;
}
.clear-btn {
background-color: #f0ad4e;
color: white;
border: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
margin-top: 20px;
}
.clear-btn:hover {
background-color: #ec971f;
}
</style>
</head>
<body>
<div class="container">
<h1>待办事项列表</h1>
<input type="text" id="todoInput" placeholder="请输入待办事项">
<button class="add-btn" onclick="addTodo()">添加待办</button>
<button class="clear-btn" onclick="clearTodos()">清空所有</button>
<ul id="todoList">
</ul>
</div>
<script>
function addTodo() {
const todoInput = document.getElementById('todoInput');
const todoList = document.getElementById('todoList');
const todoText = todoInput.value.trim();
if (todoText === '') {
alert('请输入待办事项!');
return;
}
const li = document.createElement('li');
li.textContent = todoText;
const deleteBtn = document.createElement('button');
deleteBtn.className = 'delete-btn';
deleteBtn.textContent = '删除';
deleteBtn.onclick = function() {
todoList.removeChild(li);
saveTodos();
};
li.appendChild(deleteBtn);
<!--li.ondblclick = function() {
<!-- const editText = prompt("编辑待办事项:", li.textContent);
<!-- if (editText !== null && editText.trim() !== '') {
<!-- li.textContent = editText;
<!-- }
<!-- saveTodos();
<!--};
<!--
li.onclick = function() {
li.classList.toggle('completed');
saveTodos();
};
todoList.appendChild(li);
todoInput.value = '';
saveTodos();
}
function clearTodos() {
const todoList = document.getElementById('todoList');
while (todoList.firstChild) {
todoList.removeChild(todoList.firstChild);
}
saveTodos();
}
function saveTodos() {
const todos = [];
document.querySelectorAll('#todoList li').forEach(function(li) {
todos.push({
text: li.textContent.replace('删除', '').trim(),
completed: li.classList.contains('completed')
});
});
localStorage.setItem('todos', JSON.stringify(todos));
}
function loadTodos() {
const todos = JSON.parse(localStorage.getItem('todos'));
if (todos) {
todos.forEach(function(todo) {
const li = document.createElement('li');
li.textContent = todo.text;
if (todo.completed) {
li.classList.add('completed');
}
const deleteBtn = document.createElement('button');
deleteBtn.className = 'delete-btn';
deleteBtn.textContent = '删除';
deleteBtn.onclick = function() {
li.remove();
saveTodos();
};
li.appendChild(deleteBtn);
li.ondblclick = function() {
const editText = prompt("编辑待办事项:", li.textContent);
if (editText !== null && editText.trim() !== '') {
li.textContent = editText;
}
saveTodos();
};
li.onclick = function() {
li.classList.toggle('completed');
saveTodos();
};
document.getElementById('todoList').appendChild(li);
});
}
}
loadTodos();
</script>
</body>
</html>