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

如何在JavaScript中用Local Storage存储待办项的新增与编辑值?

实现LocalStorage持久化待办列表的方案

没问题,我来帮你把现有代码改造一下,让新增、编辑的待办项都能存在LocalStorage里,刷新页面后数据也不会丢失。咱们先理清楚核心逻辑:用LocalStorage存储一个待办项数组,每个项包含唯一ID和内容;页面加载时读取数组渲染,新增/编辑/删除时同步更新数组并保存回LocalStorage。

步骤拆解与代码修改

1. 定义统一的存储Key与工具函数

先定义一个固定的LocalStorage键名,再写两个工具函数来读取和保存数据,这样代码更清晰:

// 定义LocalStorage存储的键名
const STORAGE_KEY = 'my_todo_notes';

// 从LocalStorage读取数据
function getNotes() {
  const notesStr = localStorage.getItem(STORAGE_KEY);
  return notesStr ? JSON.parse(notesStr) : [];
}

// 保存数据到LocalStorage
function saveNotes(notes) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(notes));
}

2. 页面初始化:读取并渲染已有数据

写一个初始化函数,页面加载时调用,把LocalStorage里的待办项渲染到页面上:

function initNotes() {
  const ul = document.getElementById("mynotes");
  const notes = getNotes();
  
  // 清空现有列表(避免重复渲染)
  ul.innerHTML = '';
  
  // 遍历渲染每个待办项
  notes.forEach(note => {
    createNoteElement(note.id, note.content);
  });
}

// 封装创建单个待办项元素的函数(复用新增和初始化逻辑)
function createNoteElement(id, content) {
  const ul = document.getElementById("mynotes");
  const el = document.createElement("li");
  el.setAttribute("class", "mylist");
  el.dataset.id = id; // 把ID存在元素的data属性里,方便后续操作
  
  // 处理你代码里的pin元素(这里假设是一个图标按钮,若不需要可删除)
  const pin = document.createElement("span");
  pin.setAttribute("class", "icon-pin");
  pin.innerHTML = "📌";
  
  // 删除按钮
  const cbtn = document.createElement("button");
  cbtn.setAttribute("class", "close");
  cbtn.innerHTML = "X";
  cbtn.setAttribute("onclick", "removeSticky(this)"); // 传递当前按钮元素,解决this指向问题
  
  // 内容区域
  const text = document.createElement("div");
  text.setAttribute("class", "content");
  text.setAttribute("id", `contentid_${id}`);
  text.innerHTML = content;
  text.addEventListener('click', edit); // 绑定编辑事件
  
  // 组装元素
  el.appendChild(pin);
  el.appendChild(cbtn);
  el.appendChild(text);
  ul.appendChild(el);
}

// 页面加载时执行初始化
window.addEventListener('load', initNotes);

3. 修改新增函数:同步保存到LocalStorage

原来的index变量刷新后会重置,改用现有待办项的最大ID+1作为新ID,确保唯一:

function addSticky() {
  const notes = getNotes();
  // 生成新ID:如果已有数据,取最大ID+1;否则从0开始
  const newId = notes.length > 0 ? Math.max(...notes.map(n => n.id)) + 1 : 0;
  const newContent = "Sample content";
  
  // 创建新的待办项对象并保存
  const newNote = { id: newId, content: newContent };
  notes.push(newNote);
  saveNotes(notes);
  
  // 渲染新的待办项
  createNoteElement(newId, newContent);
}

4. 修改删除函数:同步删除LocalStorage里的数据

原来的删除函数this指向有问题,现在通过传递按钮元素找到对应的待办项ID,再删除数组里的对应项:

function removeSticky(btn) {
  const ul = document.getElementById("mynotes");
  const noteEl = btn.parentNode;
  const noteId = parseInt(noteEl.dataset.id); // 取出元素上的ID
  
  // 从数组中删除对应项
  let notes = getNotes();
  notes = notes.filter(note => note.id !== noteId);
  saveNotes(notes);
  
  // 从DOM中移除元素
  ul.removeChild(noteEl);
}

5. 修改编辑函数:完成编辑后保存到LocalStorage

原来的编辑只是开启可编辑模式,现在要监听内容修改完成(比如失去焦点),然后更新LocalStorage:

function edit() {
  const textEl = this;
  textEl.contentEditable = "true";
  textEl.focus();
  
  // 监听失去焦点事件,保存编辑后的内容
  function handleBlur() {
    const noteId = parseInt(textEl.id.split('_')[1]); // 从ID中提取数字部分
    const updatedContent = textEl.innerHTML;
    
    // 更新数组中的对应项
    const notes = getNotes();
    const targetNote = notes.find(note => note.id === noteId);
    if (targetNote) {
      targetNote.content = updatedContent;
      saveNotes(notes);
    }
    
    textEl.contentEditable = "false";
    textEl.removeEventListener('blur', handleBlur); // 移除监听,避免重复绑定
  }
  
  textEl.addEventListener('blur', handleBlur);
}

完整的HTML+JS代码

把所有代码整合起来,就是这样:

<button class="addbtn icon-plus" id="addnew" onclick="addSticky()">Add</button>
<ul id="mynotes"></ul>

<script>
const STORAGE_KEY = 'my_todo_notes';

function getNotes() {
  const notesStr = localStorage.getItem(STORAGE_KEY);
  return notesStr ? JSON.parse(notesStr) : [];
}

function saveNotes(notes) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(notes));
}

function initNotes() {
  const ul = document.getElementById("mynotes");
  const notes = getNotes();
  ul.innerHTML = '';
  notes.forEach(note => {
    createNoteElement(note.id, note.content);
  });
}

function createNoteElement(id, content) {
  const ul = document.getElementById("mynotes");
  const el = document.createElement("li");
  el.setAttribute("class", "mylist");
  el.dataset.id = id;
  
  const pin = document.createElement("span");
  pin.setAttribute("class", "icon-pin");
  pin.innerHTML = "📌";
  
  const cbtn = document.createElement("button");
  cbtn.setAttribute("class", "close");
  cbtn.innerHTML = "X";
  cbtn.setAttribute("onclick", "removeSticky(this)");
  
  const text = document.createElement("div");
  text.setAttribute("class", "content");
  text.setAttribute("id", `contentid_${id}`);
  text.innerHTML = content;
  text.addEventListener('click', edit);
  
  el.appendChild(pin);
  el.appendChild(cbtn);
  el.appendChild(text);
  ul.appendChild(el);
}

function addSticky() {
  const notes = getNotes();
  const newId = notes.length > 0 ? Math.max(...notes.map(n => n.id)) + 1 : 0;
  const newContent = "Sample content";
  const newNote = { id: newId, content: newContent };
  notes.push(newNote);
  saveNotes(notes);
  createNoteElement(newId, newContent);
}

function removeSticky(btn) {
  const ul = document.getElementById("mynotes");
  const noteEl = btn.parentNode;
  const noteId = parseInt(noteEl.dataset.id);
  let notes = getNotes();
  notes = notes.filter(note => note.id !== noteId);
  saveNotes(notes);
  ul.removeChild(noteEl);
}

function edit() {
  const textEl = this;
  textEl.contentEditable = "true";
  textEl.focus();
  
  function handleBlur() {
    const noteId = parseInt(textEl.id.split('_')[1]);
    const updatedContent = textEl.innerHTML;
    const notes = getNotes();
    const targetNote = notes.find(note => note.id === noteId);
    if (targetNote) {
      targetNote.content = updatedContent;
      saveNotes(notes);
    }
    textEl.contentEditable = "false";
    textEl.removeEventListener('blur', handleBlur);
  }
  
  textEl.addEventListener('blur', handleBlur);
}

window.addEventListener('load', initNotes);
</script>

关键说明

  • 用JSON.parse和JSON.stringify处理LocalStorage的数据,因为LocalStorage只能存字符串,不能直接存数组/对象。
  • 每个待办项都有唯一ID,避免新增或删除时出现数据混乱。
  • 把创建元素的逻辑封装成createNoteElement函数,新增和初始化都复用这个函数,减少重复代码。
  • 编辑时通过blur事件监听完成编辑的时机,确保修改内容及时保存。

内容的提问来源于stack exchange,提问作者Test User

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:49:31