昨天完成了基本功能,但是大家注意刷新之后,内容都没有了。
今天我们就来解决这个刷新之后内容消失的问题。
而解决这个问题的方案,就是使用本地存储。
在使用了本地存储之后,注意在刷新操作下,内容依然还显示在页面上。
数据的操作
在引入存储之后,任务就变成了要保存的数据。
保存的数据又要拿来使用,就会有获取数据的操作。
而删除任务操作则会删除数据。
总结下来,在这个项目里,数据需要处理三种操作:保存(添加)、读取和删除。
它们发生的时间点分别在点击创建、任务列表加载和点击删除按钮。
为了代码的易读和维护,我们对原来的addTask
函数做一个调整,先从中抽出一个函数addTaskToDOM
,用于处理把任务添加到列表元素里。
同时添加以下两个函数处理数据的保存和获取:
至于删除,大家要注意,它是在动态生成的 DOM 元素里的按钮,这一部分的逻辑代码在 addTaskToDOM
里。
保存数据
function saveTasks() { const tasks = []; document.querySelectorAll('.task').forEach((task) => { tasks.push({ text: task.firstChild.textContent, completed: task.classList.contains('completed'), }); }); localStorage.setItem('tasks', JSON.stringify(tasks)); }
定义任务列表为数组,通过querySelectorAll
读取所有 CSS 类为.task 的元素,所以把数据 push 到数组。
最后通过JSON.stringify()
方法,把数组转成 JSON 格式的字符串,存储到本地存储,存储 key 为 tasks。
function addTaskToDOM(taskText, completed = false) { // 1. 创建新的任务项 const newTask = document.createElement('li'); newTask.className = 'task'; if (completed) { newTask.classList.add('completed'); } newTask.textContent = taskText; // 2. 添加完成按钮 const completeBtn = document.createElement('button'); completeBtn.textContent = '完成'; completeBtn.className = 'complete-btn'; completeBtn.addEventListener('click', () => { newTask.classList.toggle('completed'); saveTasks(); }); // 3. 添加删除按钮 const deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.className = 'delete-btn'; deleteBtn.addEventListener('click', () => { taskList.removeChild(newTask); saveTasks(); }); newTask.appendChild(completeBtn); newTask.appendChild(deleteBtn); // 将新任务项添加到任务列表中 taskList.appendChild(newTask); // 清空输入框 taskInput.value = ''; }
大家注意这一段抽出来的代码和之前不同之处,在于在完成和删除按钮的事件里,都调用了刚才实现的saveTasks()
方法。
function addTask() { const taskText = taskInput.value; if (taskText === '') { alert('任务不能为空'); return; } addTaskToDOM(taskText); saveTasks(); }
原来的 addTask
方法则重构成上面这个样子。
读取数据
加载任务数据的方法,则比较简单,只需要把数据从本地存储读取出来。
注意它是 JSON 格式的字符串,通过使用JSON.parse()
方法把它转成对象。
由于它是数组,则可以使用遍历方法forEach()
对它进行遍历后逐个加载到 DOM 里。
此时就知道为什么要抽出方法 addTaskToDOM()
了,因为这里要复用它。
function loadTasks() { const tasks = JSON.parse(localStorage.getItem('tasks')) || []; tasks.forEach((task) => { addTaskToDOM(task.text, task.completed); }); }
读取数据,需要发生在页面加载的时候,只需要监听DOMContentLoaded
事件。
document.addEventListener('DOMContentLoaded', loadTasks);
总结
完整代码如下:
// 获取DOM元素 const taskList = document.getElementById('task-list'); const taskInput = document.getElementById('task-input'); const addTaskBtn = document.getElementById('add-task-btn'); // 从localStorage加载任务 document.addEventListener('DOMContentLoaded', loadTasks); function loadTasks() { const tasks = JSON.parse(localStorage.getItem('tasks')) || []; tasks.forEach((task) => { addTaskToDOM(task.text, task.completed); }); } function saveTasks() { const tasks = []; document.querySelectorAll('.task').forEach((task) => { tasks.push({ text: task.firstChild.textContent, completed: task.classList.contains('completed'), }); }); localStorage.setItem('tasks', JSON.stringify(tasks)); } // 添加任务函数 function addTask() { const taskText = taskInput.value; if (taskText === '') { alert('任务不能为空'); return; } addTaskToDOM(taskText); saveTasks(); } function addTaskToDOM(taskText, completed = false) { // 1. 创建新的任务项 const newTask = document.createElement('li'); newTask.className = 'task'; if (completed) { newTask.classList.add('completed'); } newTask.textContent = taskText; // 2. 添加完成按钮 const completeBtn = document.createElement('button'); completeBtn.textContent = '完成'; completeBtn.className = 'complete-btn'; completeBtn.addEventListener('click', () => { newTask.classList.toggle('completed'); saveTasks(); }); // 3. 添加删除按钮 const deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.className = 'delete-btn'; deleteBtn.addEventListener('click', () => { taskList.removeChild(newTask); saveTasks(); }); newTask.appendChild(completeBtn); newTask.appendChild(deleteBtn); // 将新任务项添加到任务列表中 taskList.appendChild(newTask); // 清空输入框 taskInput.value = ''; } // 绑定事件监听器 addTaskBtn.addEventListener('click', addTask);
今天是堆积代码的一天,希望你看得快乐!
该文章在 2024/11/2 17:51:20 编辑过