在类Web开发范式(.hml/.css/.js)中,状态持久化指将应用的关键数据(如用户登录信息、设置偏好、缓存内容等)保存到本地存储,确保应用重启或页面刷新后数据不丢失。鸿蒙提供了多种本地存储API,可根据数据特性选择合适的方案,以下是具体实现方式:
一、常用存储方案及适用场景
鸿蒙类Web开发范式支持3种核心本地存储方式,各有特点:
| 存储方式 | 数据类型 | 容量限制 | 适用场景 |
|---|---|---|---|
| Preferences | 键值对(基本类型) | 单键值≤4KB,总容量≤128KB | 轻量配置(如主题设置、登录状态) |
| LocalStorage | 键值对(字符串) | 约5MB | 页面级缓存(如表单草稿、列表滚动位置) |
| File | 任意数据(二进制/文本) | 无限制(取决于设备存储) | 大量数据(如离线文件、图片缓存) |
二、具体实现方式
1. Preferences(推荐:轻量键值对存储)
Preferences是鸿蒙提供的轻量级键值存储,适合保存配置类数据,支持同步/异步操作,数据持久化到应用沙箱目录。
初始化与获取实例:
import preferences from '@ohos.data.preferences';
// 获取Preferences实例(参数为文件名,同一应用内可通过文件名区分不同存储)
let pref;
async function getPreferences() {
if (!pref) {
pref = await preferences.getPreferences(this.context, 'app_config');
}
return pref;
}
存储数据(异步):
// 保存用户登录状态
async function saveLoginState(isLogin, userInfo) {
const pref = await getPreferences();
// 支持string/number/boolean等基本类型
await pref.put('isLogin', isLogin);
await pref.put('userName', userInfo.name);
await pref.put('userId', userInfo.id);
// 必须调用flush()才会真正写入磁盘
await pref.flush();
}
读取数据(异步):
// 读取登录状态
async function getLoginState() {
const pref = await getPreferences();
// 第二个参数为默认值(若key不存在则返回)
const isLogin = await pref.get('isLogin', false);
const userName = await pref.get('userName', '');
return {
isLogin, userName };
}
删除数据:
async function clearLoginState() {
const pref = await getPreferences();
await pref.delete('isLogin');
await pref.delete('userName');
await pref.flush();
}
2. LocalStorage(页面级存储,会话级持久化)
LocalStorage是基于页面上下文的存储,数据以字符串形式保存,适合单页面内的临时缓存(应用重启后数据可能丢失,不同页面间不共享)。
使用示例:
// 保存表单草稿(同步操作)
saveFormDraft(formData) {
// 需将对象转为字符串(LocalStorage仅支持字符串值)
localStorage.setItem('formDraft', JSON.stringify(formData));
}
// 读取表单草稿
getFormDraft() {
const draftStr = localStorage.getItem('formDraft');
return draftStr ? JSON.parse(draftStr) : {
};
}
// 删除草稿
clearFormDraft() {
localStorage.removeItem('formDraft');
// 或清空所有数据:localStorage.clear();
}
注意:
- LocalStorage数据与页面绑定,页面销毁后可能被回收,不适合长期存储。
- 数据大小建议控制在5MB以内,避免影响页面性能。
3. File(文件存储,适合大量/复杂数据)
当需要存储大量数据(如离线数据库、图片缓存、复杂JSON)时,可使用文件存储API,直接操作应用沙箱内的文件。
保存JSON数据到文件:
import fileio from '@ohos.fileio';
import featureAbility from '@ohos.ability.featureAbility';
// 获取应用沙箱目录(文档目录,数据会持久化)
async function getDocDir() {
const context = featureAbility.getContext();
return await context.getFilesDir();
}
// 保存复杂数据到文件
async function saveLargeData(data) {
const docDir = await getDocDir();
const filePath = `${
docDir}/large_data.json`;
// 将对象转为字符串
const content = JSON.stringify(data);
// 写入文件(覆盖模式)
const fd = fileio.openSync(filePath, 0o2 | 0o100, 0o666); // 0o2表示写入,0o100表示创建文件
fileio.writeSync(fd, content);
fileio.closeSync(fd);
}
从文件读取数据:
async function readLargeData() {
try {
const docDir = await getDocDir();
const filePath = `${
docDir}/large_data.json`;
// 读取文件内容
const fd = fileio.openSync(filePath, 0o1); // 0o1表示只读
const buffer = new ArrayBuffer(4096); // 缓冲区大小
const readSize = fileio.readSync(fd, buffer);
fileio.closeSync(fd);
// 转换为字符串并解析JSON
const content = String.fromCharCode.apply(null, new Uint8Array(buffer.slice(0, readSize)));
return JSON.parse(content);
} catch (e) {
// 文件不存在时返回默认值
return {
list: [] };
}
}
三、状态持久化最佳实践
选择合适的存储方案
- 配置类数据(如主题、是否自动登录)→ Preferences
- 页面临时缓存(如表单草稿)→ LocalStorage
- 大量/复杂数据(如离线列表、图片)→ File
数据序列化与加密
- 存储对象/数组时,需通过
JSON.stringify()转为字符串,读取时用JSON.parse()还原。 - 敏感数据(如用户token、手机号)建议加密后存储(可使用鸿蒙提供的
@ohos.security.crypto模块)。
- 存储对象/数组时,需通过
避免频繁写入
- Preferences的
flush()操作是异步写入磁盘,频繁调用会影响性能,建议合并多次更新后再调用。 - 例如:用户修改多个设置项时,全部修改完成后再执行一次
flush()。
- Preferences的
清理过期数据
- 定期清理不再需要的存储(如缓存的临时图片、过期的会话信息),避免占用过多存储空间。
- 可在应用启动时检查数据时间戳,删除超过有效期的数据。
错误处理
- 存储操作可能因权限、磁盘空间不足等失败,需添加
try/catch捕获异常,确保应用稳定性。
- 存储操作可能因权限、磁盘空间不足等失败,需添加
总结
类Web开发范式中,状态持久化主要通过Preferences(轻量键值)、LocalStorage(页面缓存)和File(大量数据)实现,核心是根据数据特性选择合适的存储方案,并做好序列化、加密和错误处理。对于大多数场景,Preferences是性价比最高的选择,既能保证数据持久化,又能兼顾性能和易用性。