You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将已勾选待办项状态保存到localStorage,刷新后保持勾选?

待办列表完成状态本地存储修改方案

要解决待办项完成状态无法保存的问题,需要调整localStorage的存储结构,同时修改对应的读写逻辑,具体改动如下:

核心思路

将原来仅存储待办文本的字符串数组,改为存储包含text(待办内容)和completed(完成状态)的对象数组,这样就能记录每个待办的完成状态并在页面刷新后恢复。

具体代码修改

1. 修改添加待办的逻辑

在addTodo函数中,调用存储方法时传入包含状态的对象:

// 替换原有的 saveLocalTodos(todoInput.value);
saveLocalTodos({ text: todoInput.value, completed: false });

2. 更新存储函数saveLocalTodos

适配对象数组的存储逻辑:

function saveLocalTodos(todoObj) {
  let todos;
  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }
  todos.push(todoObj);
  localStorage.setItem("todos", JSON.stringify(todos));
}

3. 同步完成状态到本地存储

修改deleteCheck中完成按钮的点击事件,切换DOM类名的同时更新localStorage:

// CHECK MARK
if (item.classList[0] === "completed-button") {
  const todo = item.parentElement;
  const todoText = todo.children[0].innerText;
  todo.classList.toggle('completed');
  
  // 更新localStorage中的完成状态
  let todos = JSON.parse(localStorage.getItem("todos")) || [];
  todos = todos.map(todoItem => {
    if (todoItem.text === todoText) {
      return { ...todoItem, completed: !todoItem.completed };
    }
    return todoItem;
  });
  localStorage.setItem("todos", JSON.stringify(todos));
}

4. 渲染时恢复完成状态

修改getTodos函数,根据存储的completed属性给待办项添加对应类:

function getTodos() {
  let todos;
  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }

  todos.forEach(function(todoObj) {
    const todoDiv = document.createElement('div');
    todoDiv.classList.add('todo');
    // 根据存储的状态添加completed类
    if (todoObj.completed) {
      todoDiv.classList.add('completed');
    }
    // 创建待办文本节点
    const newTodo = document.createElement('li');
    newTodo.innerHTML = todoObj.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('completed-button');
    todoDiv.appendChild(completedButton);
    // 添加删除按钮
    const trashButton = document.createElement('button');
    trashButton.innerHTML = '<i class="fas fa-trash"></i>';
    trashButton.classList.add('trash-button');
    todoDiv.appendChild(trashButton);
    // 追加到列表
    todoList.appendChild(todoDiv);
  });
}

5. 更新删除待办的逻辑

修改removeLocalStorge函数,根据文本匹配对象进行删除:

function removeLocalStorge(todo) {
  let todos = JSON.parse(localStorage.getItem("todos")) || [];
  const todoText = todo.children[0].innerText;
  todos = todos.filter(todoItem => todoItem.text !== todoText);
  localStorage.setItem('todos', JSON.stringify(todos));
}

完整修改后的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');

//! Listeners
document.addEventListener('DOMContentLoaded', getTodos);
todoButton.addEventListener('click', addTodo);
todoList.addEventListener('click', deleteCheck);
filterOption.addEventListener('click', filterTodo);

//TODO Functions

function addTodo(event) {
  //Prevent from submitting
  event.preventDefault()
  //.Todo DIV
  const todoDiv = document.createElement('div');
  todoDiv.classList.add('todo');
  //Creat LI
  const newTodo = document.createElement('li');
  newTodo.innerHTML = todoInput.value;
  newTodo.classList.add('todo-item');
  todoDiv.appendChild(newTodo);
  //ADD TODO TO LOCALSTORAGE
  saveLocalTodos({ text: todoInput.value, completed: false });
  //CHECK MARK BUTTON
  const completedButton = document.createElement('button');
  completedButton.innerHTML = '<i class="fas fa-check"></i>';
  completedButton.classList.add('completed-button');
  todoDiv.appendChild(completedButton);
  //CHECK TRASH BUTTON
  const trashButton = document.createElement('button');
  trashButton.innerHTML = '<i class="fas fa-trash"></i>';
  trashButton.classList.add('trash-button');
  todoDiv.appendChild(trashButton);
  //APPEND TO LIST
  todoList.appendChild(todoDiv);
  //Clear Todo INPUT VALUE
  todoInput.value = '';
}

function deleteCheck(e) {
  const item = e.target;
  //DELETE TODO
  if (item.classList[0] === 'trash-button') {
    const todo = item.parentElement;
    //Animation
    todo.classList.add("fall");
    removeLocalStorge(todo);
    todo.addEventListener('transitionend', function() {
      todo.remove();
    });
  }

  //CHECK MARK
  if (item.classList[0] === "completed-button") {
    const todo = item.parentElement;
    const todoText = todo.children[0].innerText;
    todo.classList.toggle('completed');
    
    // 更新localStorage中的完成状态
    let todos = JSON.parse(localStorage.getItem("todos")) || [];
    todos = todos.map(todoItem => {
      if (todoItem.text === todoText) {
        return { ...todoItem, completed: !todoItem.completed };
      }
      return todoItem;
    });
    localStorage.setItem("todos", JSON.stringify(todos));
  }
}

function filterTodo(event) {
  const todos = todoList.childNodes;
  todos.forEach(function(todo) {
    const mStyle = todo.style;
    if (mStyle != undefined && mStyle != null) {
      switch (event.target.value) {
        case 'all':
          todo.style.display = "flex";
          break;
        case "completed":
          if (todo.classList.contains("completed")) {
            todo.style.display = "flex";
          } else {
            todo.style.display = "none";
          }
          break;
        case "uncompleted":
          if (!todo.classList.contains("completed")) {
            todo.style.display = "flex"
          } else {
            todo.style.display = "none";
          }
          break;
      }
    }
  });
}

function saveLocalTodos(todoObj) {
  //CHECK
  let todos;
  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }
  todos.push(todoObj);
  localStorage.setItem("todos", JSON.stringify(todos));
}

function getTodos() {
  let todos;

  if (localStorage.getItem("todos") === null) {
    todos = [];
  } else {
    todos = JSON.parse(localStorage.getItem("todos"));
  }

  todos.forEach(function(todoObj) {
    const todoDiv = document.createElement('div');
    todoDiv.classList.add('todo');
    // 根据存储的状态添加completed类
    if (todoObj.completed) {
      todoDiv.classList.add('completed');
    }
    //Creat LI
    const newTodo = document.createElement('li');
    newTodo.innerHTML = todoObj.text;
    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('completed-button');
    todoDiv.appendChild(completedButton);
    //CHECK TRASH BUTTON
    const trashButton = document.createElement('button');
    trashButton.innerHTML = '<i class="fas fa-trash"></i>';
    trashButton.classList.add('trash-button');
    todoDiv.appendChild(trashButton);
    //APPEND TO LIST
    todoList.appendChild(todoDiv);
  });
}

function removeLocalStorge(todo) {
  let todos = JSON.parse(localStorage.getItem("todos")) || [];
  const todoText = todo.children[0].innerText;
  todos = todos.filter(todoItem => todoItem.text !== todoText);
  localStorage.setItem('todos', JSON.stringify(todos));
}

说明:CSS和HTML部分无需修改,直接沿用原有代码即可。

内容的提问来源于stack exchange,提问作者Toxic Yamen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 10:24:05