localstorage可持久化存储习惯打卡数据,需用json.stringify()存、json.parse()读,以habit:id为key存{date:bool}对象,配合try/catch防解析失败,并用data属性精准绑定日期与习惯实现点击更新。

怎么用 localStorage 存习惯打卡数据
习惯打卡最核心的需求是“关掉页面再打开,记录还在”——这不能靠变量或数组,必须持久化。浏览器里最轻量、最直接的选择就是 localStorage,它不依赖后端,API 简单,适合单页打卡场景。
但要注意:localStorage 只能存字符串,所以得用 JSON.stringify() 存,用 JSON.parse() 读。直接存对象会变成 [object Object],后续读出来全是 undefined。
- 每次更新打卡状态(比如点“完成”),先读出原有数据 → 修改对应日期的
done: true→ 再写回localStorage - 建议用唯一 key 命名,比如
habit:drink-water,避免多个习惯互相覆盖 - 不要在页面加载时反复
JSON.parse()无效字符串——加个try...catch防止解析失败导致脚本中断
怎么生成当月打卡日历表格
不需要引入 moment.js 或 dayjs——原生 Date 就够用。关键是算清楚两个数:当月第一天是星期几(决定日历从哪列开始)、当月总天数(决定要渲染多少格)。
常见翻车点:2 月天数算错、跨年时 getMonth() 返回 0–11 导致月份错位、忽略 getDay() 返回的是 0(周日)到 6(周六)。
- 用
new Date(year, month + 1, 0).getDate()获取当月天数(比new Date(year, month + 1, -1)更稳) - 第一行空格数 =
new Date(year, month, 1).getDay(),注意周日是 0,要补 6 个空格还是 0 个,逻辑别反 - 每个格子的
data-date属性建议设成YYYY-MM-DD格式(如2024-04-05),方便和localStorage里的键对齐
点击打卡按钮怎么正确更新状态
按钮不是单纯变色,而是要精准映射到某一天、某个习惯的数据上。如果所有按钮共用一个 class、靠位置索引去查数据,换布局就全崩。
可靠做法是:按钮自带语义化信息,点击时直接提取,不依赖 DOM 顺序。
- 给按钮加
data-habit-id和data-date属性,例如:<button data-habit-id="read" data-date="2024-04-05"></button> - 事件监听用事件委托更稳妥(比如绑定在日历容器上),避免动态增删格子后监听丢失
- 更新前先检查当天是否已打卡(
if (record[date] === true)),防止重复点击误判为“取消” - 视觉反馈要即时:按钮
disabled或加doneclass,别等异步存完才变——localStorage是同步的,放心改
为什么不用 IndexedDB 而选 localStorage
因为习惯打卡数据量极小:一个习惯最多存 365 条布尔值,加起来不到 2KB。IndexedDB 的事务、版本、对象存储设计,在这里纯属杀鸡用牛刀。
真正卡住开发进度的,往往是边界情况:用户手动清了缓存、开了无痕模式、或者在 Safari 私密浏览下 localStorage 直接报 QuotaExceededError。
- Safari 私密模式下
localStorage会抛异常,必须包裹try/catch,且 fallback 方案只能是内存暂存(关页即丢) - 别存大量文本或图片 base64——
localStorage通常限 5–10MB,但实际可用空间受浏览器策略影响,保守按 2MB 设上限 - 如果真要支持多习惯+统计图表+历史导出,那才是 IndexedDB 的入场时机;现在,先跑通
setItem和getItem就够用
最易被忽略的一点:不同习惯之间数据结构最好统一,比如都用 { "2024-04-01": true, "2024-04-02": false },别有的用数组索引、有的用时间戳——后期加筛选或合并逻辑时会很难受。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











