直接用 localstorage 存待办比用文件或后端更合理,因为纯 html 页面无法读写本地文件,也不应为简单需求引入服务器;localstorage 是唯一可行的轻量方案,刷新不丢数据,且无需处理跨域或 api 请求。

为什么直接用 localStorage 存待办比用文件或后端更合理
纯 HTML 页面没法直接读写本地文件,也不该为简单待办引入服务器。用 localStorage 是唯一可行的轻量方案——它就在浏览器里,刷新不丢数据,且不用处理跨域或 API 请求。
注意:它只能存字符串,所以必须用 JSON.stringify() 和 JSON.parse() 转换;存的对象字段名别用中文或空格,否则后续筛选、排序容易出错。
- 每次写入前先
try...catch捕获QuotaExceededError,避免用户清过缓存后突然崩溃 -
localStorage.setItem('todos', JSON.stringify(todos))是标准写法,别漏掉JSON.stringify - 读取时若
localStorage.getItem('todos')返回null,要默认给空数组,而不是直接JSON.parse(null)报错
怎么让添加任务的输入框按回车就提交,而不是跳页
HTML 表单默认回车会触发表单提交,页面刷新——这对单页待办是灾难。必须阻止默认行为,再手动执行添加逻辑。
关键不是用 button,而是监听 input 的 keydown 事件,判断 event.key === 'Enter':
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault(); // 必须加,否则页面刷新
addTodo(input.value.trim());
input.value = '';
}
});
- 别只监听
keyup,keydown更及时,避免输入法组合字符被误触发 -
e.preventDefault()缺一不可,漏了就会 reload 页面 - 记得
trim()去首尾空格,否则存进localStorage的可能是空白项
勾选完成状态后,DOM 和 localStorage 怎么同步更新
不能只改 DOM(比如加个 line-through),否则刷新后状态丢失;也不能只改 localStorage,否则界面没反应。二者必须严格对应。
推荐结构:每个待办用唯一 id(如 Date.now() 或 crypto.randomUUID()),存进数组时带 done: false 字段。点击 checkbox 时,通过 id 找到对应项并 toggle done:
function toggleDone(id) {
const todos = JSON.parse(localStorage.getItem('todos') || '[]');
const todo = todos.find(t => t.id == id);
if (todo) todo.done = !todo.done;
localStorage.setItem('todos', JSON.stringify(todos));
renderList(); // 重新渲染整个列表,确保视图一致
}
- 别用
innerHTML += ...追加或局部更新,容易错位、事件绑定丢失;统一用renderList()全量重绘 - checkbox 的
checked属性必须和数据里的done字段严格同步,靠 JS 控制,不要依赖初始 HTML 的checked - 如果用了
data-id存 ID,获取时用element.dataset.id,别写成element.getAttribute('data-id')—— 前者自动转字符串,后者可能返回null
移动端点击 checkbox 太小,怎么安全放大又不破坏语义
原生 input[type="checkbox"] 在手机上点击区域太小,但直接设 width/height 会破坏可访问性(屏幕阅读器识别异常)。正确做法是隐藏原生控件,用 label 包裹文字 + 自定义样式:
<label class="todo-item"> <input type="checkbox" class="todo-checkbox"><span class="todo-text">买牛奶</span> </label>
然后 CSS 隐藏 checkbox,把 label 当点击区:
.todo-checkbox { display: none; }
.todo-item { display: flex; align-items: center; padding: 12px; }
.todo-item:hover { background: #f8f9fa; }
- 必须保留
input标签和label的包裹关系,否则无障碍支持失效 - 别用
pointer-events: none配合伪元素模拟,那样 checkbox 状态无法被 JS 正确读取 - 在 iOS 上,如果 label 内有其他可点击元素(比如删除按钮),需确保事件冒泡可控,必要时
e.stopPropagation()
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











