Skip to content

存储管理

Store 模块 提供了对浏览器全链路存储机制的统一封装。

从页面级的临时内存,到持久化的 LocalStorage/Cookie,再到海量数据的 IndexedDB,您都可以通过统一的 API 风格进行管理。

引入方式

javascript
import { tStore, tDBM } from "@techui/utils";

内存临时存储

tStore 本身即是一个轻量级的全局状态缓存池。 它基于 Map 实现,数据仅在当前页面生命周期内有效(刷新即逝)。相比 Vuex/Pinia,它更轻量,适合在非 Vue 组件环境(如纯 JS 工具函数)中共享数据。

核心 API

  • s(key, val): Set。写入数据。
  • g(key, del?): Get。读取数据。deltrue 时读取后立即删除(阅后即焚)。
  • d(key): Delete。删除数据。

场景一:跨组件/模块传参

在不引入复杂状态管理库的情况下,在两个独立的 JS 模块间共享配置。

javascript
// moduleA.js
tStore.s('appConfig', { 
  apiHost: 'https://api.techui.net',
  timeout: 5000 
});

// moduleB.js
const config = tStore.g('appConfig');
console.log(config.apiHost); // "https://api.techui.net"

场景二:一次性消息 (Flash Message)

常用于页面跳转后的成功提示,读取一次后自动销毁,防止重复显示。

javascript
// 在登录页
tStore.s('loginSuccessMsg', '欢迎回来,Ayin!');

// 在首页初始化时
const msg = tStore.g('loginSuccessMsg', true); // true 开启阅后即焚
if (msg) {
  alert(msg); // 显示欢迎
}

// 再次读取
console.log(tStore.g('loginSuccessMsg')); // undefined

tStore.cookie 提供了对 document.cookie 的简便封装,解决了原生 Cookie 操作晦涩难用的问题。

核心 API

  • s(name, val, expire): 写入。expire 为过期时间(单位:)。
  • g(name): 读取。会自动进行 unescape 解码。
  • d(name): 删除。

场景一:设置短期 Token (1小时)

javascript
// 登录成功,保存 Token,有效期 3600 秒
tStore.cookie.s('access_token', 'eyJhbGciOiJIUz...', 3600);

场景二:设置长期偏好 (7天)

javascript
// 保存用户广告偏好,7天有效
const sevenDays = 60 * 60 * 24 * 7;
tStore.cookie.s('ad_preference', 'low', sevenDays);
javascript
// 退出登录时清除
tStore.cookie.d('access_token');

// 验证是否删除
console.log(tStore.cookie.g('access_token')); // "" (空字符串)

本地存储

tStore.local 是对 localStorage 的增强封装。 它最大的特点是自动序列化:您再也不用手动写 JSON.stringifyJSON.parse 了。

核心 API

  • s(key, val): 写入。支持对象、数组、字符串等任意类型。
  • g(key): 读取。内置 JSON 解析容错。
  • d(key): 删除。

场景一:持久化用户设置

即使用户关闭浏览器,下次打开依然存在的配置。

javascript
// 写入对象
const settings = {
  theme: 'dark',
  fontSize: 14,
  sidebarCollapsed: true
};
tStore.local.s('user_settings', settings);

场景二:读取并使用

javascript
const savedSettings = tStore.local.g('user_settings');

if (savedSettings && savedSettings.theme === 'dark') {
  enableDarkMode();
}

场景三:容错处理

假设某个 Key 被外部脚本被错误地写入了非 JSON 字符串(如 "undefined"),tStore 会优雅降级返回原字符串,而不会报错导致页面白屏。

javascript
// 模拟脏数据
localStorage.setItem('bad_data', '{ key: "invalid json" }'); // 缺少引号的非法JSON

const val = tStore.local.g('bad_data');
console.log(val); // 原样返回字符串 '{ key: "invalid json" }',不会抛出 SyntaxError

会话存储

tStore.session 的 API 与 local 完全一致,但数据仅在当前标签页关闭前有效。

场景一:表单临时草稿

用户填写长表单时不小心刷新了页面,数据不应丢失;但关闭标签页后应清除,避免污染下次操作。

javascript
// 监听输入框变化
input.addEventListener('input', (e) => {
  tStore.session.s('form_draft_title', e.target.value);
});

// 页面加载时恢复
const draft = tStore.session.g('form_draft_title');
if (draft) input.value = draft;

场景二:页面访问面包屑

记录用户在当前会话中的访问路径。

javascript
const history = tStore.session.g('breadcrumbs') || [];
history.push({ name: 'UserDetail', id: 101 });
tStore.session.s('breadcrumbs', history);

浏览器数据库管理

tDBM (TechUI Database Manager) 是本模块中最强大的工具。 它将复杂的 IndexedDB 操作封装为简单的 Promise 调用,适合存储大量结构化数据(如日志、离线文档、大屏数据缓存)。

初始化结构 (Init)

在使用前,必须先定义数据库表结构(Schema)。

javascript
// 定义表结构
const stores = [
  {
    name: 'logs',         // 表名
    keyPath: 'id',        // 主键
    autoIncrement: true,  // 自增
    indexes: [            // 索引
      { name: 'level', keyPath: 'lvl' },
      { name: 'date', keyPath: 'timestamp' }
    ]
  },
  {
    name: 'cache_files',
    keyPath: 'url'        // 使用 URL 作为主键
  }
];

// 初始化数据库 'MyAppDB',版本号 1
await tDBM.init('MyAppDB', 1, stores);

场景一:批量写入 (高性能)

比循环调用 add 快得多,适合初始化导入数据。

javascript
const logs = [
  { lvl: 'info', msg: 'App started', timestamp: Date.now() },
  { lvl: 'error', msg: 'Network error', timestamp: Date.now() + 100 },
  // ... 更多数据
];

// 批量插入
await tDBM.add('logs', logs);
console.log('日志写入完成');

场景二:更新或插入 (Upsert)

用于同步服务器数据,如果 ID 存在则更新,不存在则新增。

javascript
const userProfile = {
  url: '/api/user/1',
  data: { name: 'Ayin', role: 'admin' },
  cachedAt: Date.now()
};

// 使用 put 方法
await tDBM.put('cache_files', userProfile);

场景三:按索引查询

不通过 ID,而是通过业务字段查询。

javascript
// 查询所有 'error' 级别的日志
const errors = await tDBM.getByIndex('logs', 'level', 'error');
console.log(`共发现 ${errors.length} 条错误日志`);

场景四:大数据量游标遍历

当表中存有几万条数据时,直接 getAll 会导致内存溢出。使用 iterate 游标逐条处理。

javascript
// 遍历所有日志
await tDBM.iterate('logs', (cursor, value) => {
  if (value.timestamp < Date.now() - 86400000) {
    // 删除 1 天前的过期日志
    cursor.delete(); 
    console.log('已删除过期日志:', value.id);
  }
});

场景五:数据库信息查看与维护

javascript
// 检查数据库是否已连接
if (tDBM.isInited()) {
  const info = tDBM.info();
  console.log(`当前数据库版本: ${info.version}, 包含表: ${info.tables.join(',')}`);
}

// 彻底删除数据库 (需先关闭连接)
tDBM.close();
await tDBM.deleteDatabase('MyAppDB');