Skip to content

浏览器本地存储

简介

使用浏览器本地存储保存离线小说、用户自定义的阅读器样式和文件夹树结构等数据。

实现细节

技术选型

项目使用 localforage 提供统一的异步存储 API。它会根据浏览器能力选择 IndexedDB、WebSQL 或 localStorage 等驱动;实际可用容量取决于浏览器和所选驱动,不能笼统认为存储空间一定更大。与原生 localStorage 不同,读写操作是异步的,也可以直接保存对象等结构化数据。

模块实现

增加存储模块,包括获取和设置存储的函数,存储字段的 keys,代码如下

// src/utils/store.js
import localforage from "localforage";

// 本地存储读写均为异步操作。
async function getLocalValue(key) {
  return localforage.getItem(key);
}

function setLocalValue(key, value) {
  return localforage.setItem(key, value);
}

export const NOVEL_READER_STYLE_SAVE_KEY = "novel-reader-style";
export const LOCAL_NOVELS_SAVE_KEY = "local-novels";
export const FOLDER_TREE_SAVE_KEY = "folder-tree";

export { getLocalValue, setLocalValue };

其中不同存储字段的 key 和对应的 value 含义如下

key 中文含义 value 示例
NOVEL_READER_STYLE_SAVE_KEY 用户设置的阅读器样式 { opacity: 0.8, width: "20px" }
LOCAL_NOVELS_SAVE_KEY 离线模式下保存的小说 小说对象或对象数组
FOLDER_TREE_SAVE_KEY 用户设置的目录结构 目录树对象

接口设计与实现

存储模块对外提供 getLocalValue、setLocalValue 两个函数以及存储字段 key。

系统功能界面,调用存储函数设置或获取本地存储。

// App.js
import {
  getLocalValue,
  setLocalValue,
  NOVEL_READER_STYLE_SAVE_KEY,
} from "./utils/store";

// 1. 界面初始化:读取配置;没有已保存的值时使用默认配置。
async function initDataFromLocalStore() {
  const savedStyle = await getLocalValue(NOVEL_READER_STYLE_SAVE_KEY);
  setStyle(savedStyle ?? DEFAULT_STYLE);
}

// 2. 用户修改样式后保存。localforage 支持直接保存对象。
async function saveStyle(style) {
  await setLocalValue(NOVEL_READER_STYLE_SAVE_KEY, style);
}

单元测试

单元测试,包括对各个模块进行的单元测试和测试结果等。

浏览器存储测试可在测试环境中 mock localforage,或使用提供 IndexedDB 的测试环境;不能仅因单元测试运行在 Node.js 中就断定无法测试。

如需在 Node.js 环境中模拟 Web Storage,可考虑使用 node-localstorage;它不等同于浏览器中的 IndexedDB。

版本历史

1.0 版本,支持浏览器原生的 localStorage 存储阅读器样式。

1.3 版本,支持第三方库 localforage 存储阅读器样式。

文档中已定义 LOCAL_NOVELS_SAVE_KEY;本地小说是否已通过该 key 完整持久化,应以对应版本的客户端实现为准。

参考文献