使用Ajax将待办列表条目存入数据库解决页面刷新数据丢失问题
方案1:使用localStorage实现本地持久化(无需后端,最适合新手场景)
localStorage是浏览器自带的本地存储能力,无需额外服务端代码即可实现刷新后数据不丢失,只需要修改你的JS代码,增加存储、读取、更新本地数据的逻辑即可,完整修改后的代码如下:
//selectors const todoInput = document.querySelector('.todo_input'); const todoButton = document.querySelector('.todo_button'); const todoList = document.querySelector('.todo_list'); const filterOption = document.querySelector('.filter_todo'); //event listeners document.addEventListener('DOMContentLoaded', getLocalTodos); // 页面加载先读本地数据 todoButton.addEventListener("click", addTodo) todoList.addEventListener("click", deleteCheck) filterOption.addEventListener("click", filterTodo) //functions function addTodo(event) { event.preventDefault(); if(todoInput.value === ""){ return null } //todo DIV const todoDiv = document.createElement('div'); todoDiv.classList.add('todo'); //todo LI const newTodo = document.createElement('li'); newTodo.innerText = todoInput.value; newTodo.classList.add('todo_item'); todoDiv.appendChild(newTodo); //check mark BUTTON const completedButton = document.createElement('button'); completedButton.innerHTML = '<i class="fas fa-check"></i>'; completedButton.classList.add('complete_btn') todoDiv.appendChild(completedButton); //delete BUTTON const deleteButton = document.createElement('button'); deleteButton.innerHTML = '<i class="fas fa-trash"></i>'; deleteButton.classList.add('delete_btn') todoDiv.appendChild(deleteButton); //Append to Actual LIST todoList.appendChild(todoDiv); // 保存到本地存储 saveLocalTodos(newTodo.innerText); //Clear todo input VALUE todoInput.value = "" } //DELETE & CHECK function deleteCheck(e) { const item = e.target; //DELETE ITEM if (item.classList[0] === "delete_btn") { const todo = item.parentElement; // 先删本地存储的数据 removeLocalTodos(todo); //ANIMATION TRANSITION todo.classList.add("fall") todo.addEventListener('transitionend', function () { todo.remove() }) } //COMPLETE ITEM if (item.classList[0] === "complete_btn") { const todo = item.parentElement; todo.classList.toggle("completedItem") // 更新本地存储的完成状态 updateLocalTodoStatus(todo); } } //FILTERING THE TASKS ACCORDING THE OPTION function filterTodo(e) { const todos = todoList.childNodes; for(let i = 1; i<todos.length; i++ ){ switch (e.target.value) { case "all": todos[i].style.display = "flex"; break; case "completed": if (todos[i].classList.contains('completedItem')) { todos[i].style.display = "flex"; } else { todos[i].style.display = "none"; } break; case "uncompleted": if (!todos[i].classList.contains('completedItem')) { todos[i].style.display = "flex"; } else { todos[i].style.display = "none"; } break; } } } // -------------localStorage相关工具函数------------- // 保存新待办到本地 function saveLocalTodos(todoText) { let todos = JSON.parse(localStorage.getItem('todos')) || []; todos.push({text: todoText, completed: false}); localStorage.setItem('todos', JSON.stringify(todos)); } // 读取本地待办渲染到页面 function getLocalTodos() { let todos = JSON.parse(localStorage.getItem('todos')) || []; todos.forEach(todo => { const todoDiv = document.createElement('div'); todoDiv.classList.add('todo'); if(todo.completed) todoDiv.classList.add('completedItem'); const newTodo = document.createElement('li'); newTodo.innerText = todo.text; newTodo.classList.add('todo_item'); todoDiv.appendChild(newTodo); const completedButton = document.createElement('button'); completedButton.innerHTML = '<i class="fas fa-check"></i>'; completedButton.classList.add('complete_btn') todoDiv.appendChild(completedButton); const deleteButton = document.createElement('button'); deleteButton.innerHTML = '<i class="fas fa-trash"></i>'; deleteButton.classList.add('delete_btn') todoDiv.appendChild(deleteButton); todoList.appendChild(todoDiv); }) } // 删除本地存储的对应待办 function removeLocalTodos(todoEl) { let todos = JSON.parse(localStorage.getItem('todos')) || []; const targetText = todoEl.querySelector('.todo_item').innerText; todos = todos.filter(todo => todo.text !== targetText); localStorage.setItem('todos', JSON.stringify(todos)); } // 更新本地待办的完成状态 function updateLocalTodoStatus(todoEl) { let todos = JSON.parse(localStorage.getItem('todos')) || []; const targetText = todoEl.querySelector('.todo_item').innerText; const targetIndex = todos.findIndex(todo => todo.text === targetText); todos[targetIndex].completed = !todos[targetIndex].completed; localStorage.setItem('todos', JSON.stringify(todos)); }
小提示:你可以把HTML里写死的Tomatoes默认待办删掉,避免和localStorage渲染的内容重复,如果需要保留默认值,在getLocalTodos函数里判断todos为空的时候主动加进去即可。
方案2:使用AJAX实现服务端持久化(多设备同步需要)
如果需要跨设备访问同一份待办数据,才需要用到AJAX方案,前提是你先写好对应的后端接口,包括:
- 待办列表获取接口:GET请求返回所有待办的JSON数组
- 新增待办接口:POST请求接收待办文本、完成状态,写入数据库
- 删除待办接口:请求接收待办唯一标识,删除对应数据库记录
- 状态更新接口:请求接收待办唯一标识、新状态,更新数据库记录
新增待办的AJAX示例(用原生fetch实现):
// 可以替换到addTodo函数里保存localStorage的位置 fetch('/save_todo.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: newTodo.innerText, completed: false }) }).then(res => res.json()) .then(data => { // 接口返回成功后的处理逻辑 })
初学建议先把localStorage方案跑通,再学习AJAX相关的后端交互逻辑。
内容的提问来源于stack exchange,提问作者R3nrs
相关产品推荐
相关产品推荐

