旧物集的物品故事:时间线与收藏管理
如果你喜欢收藏旧物,推荐去鸿蒙应用市场搜一下**「旧物集」**,下载体验体验。记录珍藏物品、写物品故事、按时间线浏览,一套走下来对每件珍藏都会有更完整的记录。体验完再回来看这篇文章,你会更清楚时间线浏览和收藏管理背后是怎么实现的。
写在前面
大家好,我是一名写了十多年Web前端的老兵。从jQuery时代一路走到React/Vue,CSS3动画、requestAnimationFrame、Web Animation API这些都算是看家本领。去年开始转战鸿蒙生态,用ArkTS开发App,这一路踩了不少坑,也积累了不少心得。
很多人觉得"前端转鸿蒙"应该很容易------都是写UI嘛,组件化、状态管理、生命周期,概念都差不多。但真正上手之后你会发现,相似的地方让你觉得亲切,不同的地方让你抓狂。
比如:
- 时间线渲染 :React的
map()变成了ForEach,分组逻辑需要自己处理。 - 数据存储 :Web的
localStorage到了ArkTS变成了@ohos.data.preferences。 - 收藏交互 :Web的点击事件变成了鸿蒙的
onClick。
接下来这篇文章,我会用"旧物集"的实际开发经历,带你看看物品时间线、收藏管理、数据统计的实现。
这篇文章聊什么
旧物集的物品故事功能,核心要解决三个问题:
- 时间线:按年份浏览珍藏物品
- 收藏管理:收藏重要物品
- 数据统计:分析收藏数据
第一步:时间线页面
typescript
@Entry
@Component
struct TimelinePage {
@State items: CollectibleItem[] = []
@State groupedByYear: Record<string, CollectibleItem[]> = {}
async aboutToAppear() {
await this.loadItems()
this.groupItems()
}
async loadItems() {
const store = await preferences.getPreferences(getContext(), 'jiuwuji_data');
const stored = await store.get('items', '[]') as string;
this.items = JSON.parse(stored);
this.items.sort((a, b) =>
new Date(b.acquiredDate).getTime() - new Date(a.acquiredDate).getTime()
);
}
groupItems() {
this.groupedByYear = {};
this.items.forEach(item => {
const year = new Date(item.acquiredDate).getFullYear().toString();
if (!this.groupedByYear[year]) {
this.groupedByYear[year] = [];
}
this.groupedByYear[year].push(item);
});
}
build() {
Column() {
Text('物品时间线')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 16 })
List({ space: 16 }) {
ForEach(Object.entries(this.groupedByYear), ([year, yearItems]) => {
ListItem() {
Column() {
Text(year)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#F59E0B')
.margin({ bottom: 12 })
ForEach(yearItems, (item: CollectibleItem) => {
Row() {
Column() {
Circle({ width: 12, height: 12 })
.fill('#F59E0B')
Row()
.width(2)
.height(80)
.backgroundColor('#374151')
}
.margin({ right: 12 })
Column() {
Row() {
Text(this.getCategoryIcon(item.category))
.fontSize(20)
Text(item.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.margin({ left: 8 })
}
Text(item.story)
.fontSize(14)
.fontColor('#D1D5DB')
.margin({ top: 8 })
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.layoutWeight(1)
.padding(12)
.backgroundColor('#1F2937')
.borderRadius(12)
}
.margin({ bottom: 12 })
})
}
}
})
}
.layoutWeight(1)
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#111827')
}
private getCategoryIcon(category: string): string {
return ITEM_CATEGORIES.find(c => c.id === category)?.icon || '🎁';
}
}
第二步:收藏管理
typescript
@Entry
@Component
struct FavoritesPage {
@State favorites: CollectibleItem[] = []
async aboutToAppear() {
const store = await preferences.getPreferences(getContext(), 'jiuwuji_data');
const stored = await store.get('items', '[]') as string;
const items: CollectibleItem[] = JSON.parse(stored);
this.favorites = items.filter(i => i.isFavorite);
}
build() {
Column() {
Text('珍藏物品')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 16 })
if (this.favorites.length === 0) {
Text('还没有珍藏的物品')
.fontSize(16)
.fontColor('#9CA3AF')
} else {
List({ space: 12 }) {
ForEach(this.favorites, (item: CollectibleItem) => {
ListItem() {
Row() {
if (item.photoUri) {
Image(item.photoUri)
.width(60)
.height(60)
.objectFit(ImageFit.Cover)
.borderRadius(8)
}
Column() {
Text(item.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(this.getCategoryName(item.category))
.fontSize(13)
.fontColor('#9CA3AF')
.margin({ top: 4 })
}
.layoutWeight(1)
.margin({ left: 12 })
}
.width('100%')
.padding(12)
.backgroundColor('#1F2937')
.borderRadius(12)
}
})
}
.layoutWeight(1)
}
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#111827')
}
private getCategoryName(category: string): string {
return ITEM_CATEGORIES.find(c => c.id === category)?.name || category;
}
}
第三步:数据统计
typescript
interface ItemStats {
totalItems: number;
favoriteCount: number;
categoryDistribution: Record<string, number>;
statusDistribution: Record<string, number>;
}
总结
这篇文章围绕"旧物集"的物品故事功能,讲解了三个核心主题:
- 时间线:按年份分组的物品时间线
- 收藏管理:珍藏物品的筛选和展示
- 数据统计:物品分类和状态的统计分析
时间线的核心是数据分组------用Record<string, CollectibleItem[]>按年份分组。
如果你喜欢收藏旧物,希望这篇文章能帮你理解旧物集背后的管理逻辑。去鸿蒙应用市场下载体验一下吧,有问题欢迎交流。