用indexeddb实现离线日历存储,核心是将日程作为结构化记录存入calendardb数据库的events对象仓库,通过date和updatedat索引支持按天查询与排序,统一用yyyy-mm-dd字符串存日期,封装增删改查方法并处理异步错误。

用 IndexedDB 实现离线日历日程存储,核心是把每条日程当作一条结构化记录存进数据库,支持增删改查、按日期范围检索,并在页面加载时自动同步显示。关键在于设计合理的数据库结构、封装可靠的操作方法,以及处理好日期与 IndexedDB 的兼容性(比如用时间戳或标准字符串格式)。
设计数据库与对象仓库
创建一个名为 calendarDB 的数据库,版本设为 1;定义一个叫 events 的对象仓库,主键用自增的 id,同时添加两个重要索引:date(用于按天查日程)和 updatedAt(便于同步或排序)。日期字段推荐统一存为 YYYY-MM-DD 字符串(如 "2024-06-15"),避免时区和 Date 对象序列化问题。
- 打开数据库时检查版本,升级时新建仓库并建立索引
-
date索引设为unique: false,允许多条日程同一天 - 避免直接存
new Date()对象——IndexedDB 不保证其序列化一致性,转成字符串或时间戳更稳妥
封装增删改查操作
为简化调用,封装几个常用方法:添加日程时生成唯一 ID 并写入 date 字段;查询某天所有日程,用 index.getAll() 配合 IDBKeyRange.only();更新时先 get 再 put;删除直接用 delete()。
- 添加示例:
addEvent({ title: "会议", date: "2024-06-15", time: "14:00" }) - 查当天日程:
getEventsByDate("2024-06-15")→ 返回 Promise 数组 - 更新时务必传入完整对象(含 id),IndexedDB 没有部分更新概念
初始化日历视图并绑定离线逻辑
页面加载后,先尝试从 IndexedDB 加载当月日程,渲染到日历格子中;所有添加/编辑操作都先写库再更新 UI,确保离线状态下数据不丢失。监听 online 和 offline 事件可提示用户当前状态,但无需强制同步——日程本身就是最终数据源,无服务端时也完全可用。
- 渲染前做一次
getAll()或按需查多天(例如月初到月末),减少请求次数 - 点击某天弹出表单时,自动填入该日期,提交即调用
addEvent - 删除某条日程后,立即从 DOM 移除对应元素,并触发 DB 删除
处理边界与容错
IndexedDB 操作是异步且可能失败的(如空间不足、用户禁用、版本冲突),每个 API 调用都应包裹 try/catch 并提供降级反馈。例如添加失败时,在 UI 显示“保存失败,请重试”,而不是静默忽略。
- 打开数据库失败时,提示“浏览器不支持离线存储”,并禁用编辑功能
- 批量操作(如导入一周日程)建议用
transaction包裹,确保原子性 - 开发阶段可在 DevTools > Application > Storage 中手动清空 IndexedDB 方便调试











