用 localStorage 打造本地待办清单:一个轻量级的前端实践
2025年11月22日 16:41
用 localStorage 打造本地待办清单:一个轻量级的前端实践
在现代网页开发中,我们常常需要在浏览器端保存一些用户数据,比如用户的偏好设置、临时输入内容,或者像本文要实现的——一个本地待办事项列表(Todo List)。借助浏览器提供的 localStorage,我们可以轻松地将数据持久化存储在用户的设备上,即使关闭页面或重启浏览器,数据也不会丢失。
localStorage 是什么?
localStorage 是 Web Storage API 的一部分,它为每个域名提供了一块独立的存储空间。它的特点是:
- 永久存储:除非用户手动清除或通过代码删除,否则数据不会过期。
-
键值对结构:所有数据都以字符串形式存储,因此通常需要配合
JSON.stringify()和JSON.parse()来处理对象。 - 同源策略限制:只能被同一协议、域名和端口下的页面访问。
实现一个本地待办清单
下面是一个完整的待办清单示例,使用 HTML、CSS 和原生 JavaScript 构建,并利用 localStorage 实现数据持久化。
HTML 结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LOCAL TAPAS</title>
<link rel="stylesheet" href="./common.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" placeholder="Item Name" required name="item">
<input type="submit" value="+ Add Item">
</form>
</div>
<!-- JavaScript 脚本 -->
</body>
</html>
页面包含一个标题、一个待办项列表容器(<ul class="plates">)以及一个用于添加新事项的表单。
CSS 样式亮点
html {
box-sizing: border-box;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
*, *::before, *::after {
box-sizing: inherit;
}
.plates li {
display: flex;
}
.plates input {
display: none;
}
.plates input + label:before {
content: "⬜️";
margin-right: 10px;
}
.plates input:checked + label:before {
content: "✅";
}
这里有几个关键点:
- 使用
flex布局让页面整体居中,同时让每个待办项内部也采用弹性布局。 - 利用
input[type=checkbox]配合label和伪元素::before实现自定义复选框样式。 -
outline属性用于高亮输入框焦点状态,且不占用盒模型空间。 -
overflow: hidden可防止子元素溢出父容器(虽然本例未直接使用,但属于常用技巧)。
注意:CSS 中并非所有属性都会继承。例如
font-size、color会从父元素继承,而background、width、height等则不会。开发者需根据需求显式设置。
JavaScript 逻辑
核心逻辑围绕三个函数展开:
1. 初始化数据
const items = JSON.parse(localStorage.getItem('todos')) || [];
尝试从 localStorage 中读取名为 'todos' 的数据,若不存在则初始化为空数组。
2. 渲染列表
function populateList(plates = [], platesList) {
platesList.innerHTML = plates.map((plate, i) => `
<li>
<input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label for="item${i}">${plate.text}</label>
</li>
`).join('');
}
该函数接收待办项数组和 DOM 容器,动态生成带复选框的列表项,并通过 data-index 记录索引以便后续操作。
3. 添加与切换状态
function addItem(event) {
event.preventDefault();
const text = this.querySelector('[name=item]').value.trim();
if (!text) return;
items.push({ text, done: false });
localStorage.setItem('todos', JSON.stringify(items));
populateList(items, itemsList);
this.reset();
}
function toggleDone(event) {
if (event.target.tagName === 'INPUT') {
const index = event.target.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('todos', JSON.stringify(items));
populateList(items, itemsList);
}
}
- 表单提交时阻止默认刷新行为,提取输入值并存入
items数组。 - 点击复选框时,根据
data-index更新对应项的完成状态。 - 每次变更后立即同步到
localStorage,确保数据持久化。
最后绑定事件监听器:
addItems.addEventListener('submit', addItem);
itemsList.addEventListener('click', toggleDone);
populateList(items, itemsList); // 初次渲染
小结
这个“Local Tapas”(本地小食清单)虽小,却完整展示了前端开发中的多个核心概念:
-
数据持久化:通过
localStorage实现无服务器依赖的本地存储。 - DOM 操作与事件委托:高效更新界面,避免重复绑定事件。
- CSS 继承与布局:理解哪些样式可继承,合理使用 Flexbox 实现响应式结构。
- 函数式思维:将逻辑封装为可复用函数,提升代码可读性与维护性。
无需后端、不依赖框架,仅用浏览器原生能力,就能构建一个实用又美观的交互应用——这正是现代 Web 开发的魅力所在。