【OpenHarmony/HarmonyOs 】化学学习 App 收藏夹功能实践:AppStorage 本地持久化与响应式刷新
【OpenHarmony/HarmonyOs 】化学学习 App 收藏夹功能实践:AppStorage 本地持久化与响应式刷新
收藏夹是学习类 App 中非常重要的功能。用户遇到常用元素、难记方程式、重点知识点时,都希望能一键保存,后续快速复习。本文结合我的「化学视界」项目,聊聊我是如何开发收藏功能的。⭐
一、为什么收藏功能不能只做一个按钮?
刚开始做收藏时,很容易以为只要在详情页放一个爱心按钮就够了。但真正开发后会发现,收藏系统至少要解决几个问题:
- 用户能收藏哪些内容?
- 收藏后如何持久保存?
- 多个页面之间如何同步收藏状态?
- 收藏夹如何分类展示?
- 取消收藏后列表如何刷新?
- 点击收藏项如何回到详情页?
我的项目里,收藏对象包括三类:
- ⚛️ 元素。
- ⚗️ 方程式。
- 📚 知识点。
所以我先设计了统一的收藏数据结构,而不是给每种内容单独写一套逻辑。
二、收藏数据结构设计
收藏项定义如下:
export type FavoriteType = 'element' | 'equation' | 'knowledge';
export interface FavoriteItem {
id: string;
type: FavoriteType;
title: string;
subtitle: string;
dateAdded: string;
}
这里的几个字段分别解决不同问题:
id:定位原始内容。type:区分元素、方程式、知识点。title:收藏夹列表主标题。subtitle:辅助说明,比如元素符号、方程式内容、知识标签。dateAdded:记录收藏时间。
我开发时的一个经验是:收藏夹列表不要只存 id。只存 id 虽然最干净,但列表展示时还要反查原始数据。适当冗余 title 和 subtitle,可以让收藏夹展示更直接。
三、使用 AppStorage 保存收藏数据
收藏数据写入本地状态:
function writeFavorites(items: FavoriteItem[]): void {
AppStorage.setOrCreate(STORAGE_KEY, JSON.stringify(items));
const marker = (AppStorage.get<number>(STORAGE_VERSION_KEY) ?? 0) + 1;
AppStorage.setOrCreate(STORAGE_VERSION_KEY, marker);
}
这里有一个关键点:我除了保存收藏数组,还额外维护了一个刷新标记。
原因是收藏可能发生在多个页面:
- 元素详情页点击收藏。
- 方程式详情页点击收藏。
- 知识详情页点击收藏。
- 收藏夹里取消收藏。
如果没有统一刷新机制,某个页面的收藏状态很容易滞后。
四、添加收藏:先去重再写入
添加收藏时,我先读取已有收藏,再判断是否已经收藏过:
export function addFavorite(type: FavoriteType, id: string, title: string): boolean {
const items = readFavorites();
if (items.some(item => item.type === type && item.id === id)) {
return false;
}
items.push({
id,
type,
title,
subtitle: getSubtitle(type, id),
dateAdded: formatDate(new Date())
});
writeFavorites(items);
return true;
}
这里我用 type + id 判断唯一性,因为元素、方程式、知识点可能都有数字 id,单独用 id 不够安全。
五、切换收藏状态:详情页最常用
详情页里一般不需要关心“添加”还是“删除”,只要调用切换函数:
export function toggleFavorite(type: FavoriteType, id: string, title: string): boolean {
const items = readFavorites();
const idx = items.findIndex(item => item.type === type && item.id === id);
if (idx >= 0) {
removeFavorite(type, id);
return false;
} else {
addFavorite(type, id, title);
return true;
}
}
元素详情页中就是这样使用的:
handleFavoriteClick() {
if (this.elementLocal) {
const newState = toggleFavorite(
'element',
String(this.elementLocal.number),
this.elementLocal.name
);
animateTo({ duration: 300, curve: Curve.EaseOut }, () => {
this.isFavorite = newState;
});
}
}
这样详情页逻辑就很清楚:点击按钮 → 切换状态 → 更新 UI。
六、收藏夹页面:用 StorageLink 自动响应变化
收藏夹页面使用刷新标记监听收藏变化:
@StorageLink(FAVORITES_VERSION_KEY)
@Watch('onVersionChange')
version: number = 0;
当收藏数据变化时,页面重新加载收藏列表:
onVersionChange() {
this.watchVersionChange();
}
watchVersionChange() {
this.allFavorites = getAllFavorites();
this.updateFilteredFavorites();
}
我当时这样设计,是为了避免在每个页面之间手动传递事件。收藏数据变化后,只要刷新标记变化,收藏夹自然更新。
七、收藏夹分类展示
收藏夹顶部有四个分类:
- 全部。
- 元素。
- 方程式。
- 知识。
过滤逻辑如下:
updateFilteredFavorites(): void {
if (this.selectedTab === 0) {
this.filteredFavorites = this.allFavorites;
} else if (this.selectedTab === 1) {
this.filteredFavorites = this.allFavorites.filter(
(f: FavoriteItem) => f.type === 'element'
);
} else if (this.selectedTab === 2) {
this.filteredFavorites = this.allFavorites.filter(
(f: FavoriteItem) => f.type === 'equation'
);
} else {
this.filteredFavorites = this.allFavorites.filter(
(f: FavoriteItem) => f.type === 'knowledge'
);
}
}
这部分我没有做复杂抽象,因为分类只有几种,直接写清楚反而更容易维护。
八、从收藏夹跳回详情页
收藏夹不能只是一个静态列表,点击收藏项后应该回到对应详情页:
navigateToDetail(item: FavoriteItem) {
if (item.type === 'element') {
router.pushUrl({
url: 'pages/periodic/ElementDetail',
params: { elementNumber: Number(item.id) }
});
} else if (item.type === 'equation') {
router.pushUrl({
url: 'pages/equations/EquationDetail',
params: { equationId: Number(item.id) }
});
} else if (item.type === 'knowledge') {
router.pushUrl({
url: 'pages/knowledge/KnowledgeDetail',
params: { knowledgeId: Number(item.id) }
});
}
}
这也是我前面统一收藏结构的好处:一个 type 就能决定跳转目标。
九、开发中遇到的关键点
1. 收藏状态要跨页面一致
如果只在当前页面维护 isFavorite,收藏夹不会自动刷新。所以我用了刷新标记做全局同步。
2. 收藏项要有展示字段
只保存 id 会让收藏夹很难展示,所以我保存了 title 和 subtitle。
3. 删除收藏要走统一方法
无论是在详情页取消收藏,还是收藏夹里删除,都调用同一套工具函数,避免数据不一致。
十、总结
收藏功能看起来简单,但要做完整,需要处理数据结构、持久化、状态同步、分类展示和详情跳转。
我的实现思路是:
- ⭐ 用统一结构保存不同类型内容。
- 💾 用本地状态保存收藏列表。
- 🔄 用刷新标记驱动页面自动更新。
- 🧭 用
type + id实现详情跳转。 - 🎨 用分类和图标提升可读性。
对于学习类 App 来说,收藏夹不只是“保存喜欢的内容”,更是用户复习路径的一部分。把收藏功能做扎实,整个学习闭环才会更完整。

更多推荐


所有评论(0)