昨天完成了基本功能,但是大家注意刷新之后,内容都没有了。

今天我们就来解决这个刷新之后内容消失的问题。
而解决这个问题的方案,就是使用本地存储。
 
在使用了本地存储之后,注意在刷新操作下,内容依然还显示在页面上。
数据的操作
在引入存储之后,任务就变成了要保存的数据。
保存的数据又要拿来使用,就会有获取数据的操作。
而删除任务操作则会删除数据。
总结下来,在这个项目里,数据需要处理三种操作:保存(添加)、读取和删除。
它们发生的时间点分别在点击创建、任务列表加载和点击删除按钮。
为了代码的易读和维护,我们对原来的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 编辑过