news 2026/7/2 1:59:22

OpenHarmony 英语学习 App 实战:自定义生词本、持久化存储与学习数据管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenHarmony 英语学习 App 实战:自定义生词本、持久化存储与学习数据管理

OpenHarmony 英语学习 App 实战:自定义生词本、持久化存储与学习数据管理

摘要

英语学习 App 不能只提供固定词库。真实学习中,用户会从课本、阅读、听力、影视台词里遇到自己的生词,因此“自定义生词本”是非常重要的功能。本文以「英语视界 YingYu」项目为例,分享如何在 OpenHarmony/HarmonyOS 中实现自定义生词本、详情弹窗、添加表单、搜索过滤和本地持久化。📘

相关文件包括:

entry/src/main/ets/pages/CustomWordBook.ets entry/src/main/ets/utils/StorageService.ts entry/src/main/ets/model/DataModels.ts entry/src/main/ets/utils/YingYuPreferences.ts

一、自定义生词本要解决什么问题?

固定词库适合系统学习,但用户自己的生词更有价值:

  • 课外阅读遇到的词;
  • 老师补充的重点词;
  • 听力材料里的陌生词;
  • 错题中反复出现的词;
  • 考试作文常用表达。

所以自定义生词本需要具备:

  • 添加单词;
  • 保存音标、释义、例句、标签;
  • 查看详情;
  • 搜索过滤;
  • 参与复习系统;
  • 本地持久化保存。

二、数据模型:CustomWord

项目中使用CustomWord表示一个自定义单词:

export interface CustomWord {id:stringword:stringphonetic?:stringtranslation:stringexample?:stringtags:string[] createdAt:stringreviewCount:numbermastered:boolean}

字段设计比较完整:

  • id:唯一标识;
  • word:英文单词;
  • phonetic:可选音标;
  • translation:中文释义;
  • example:可选例句;
  • tags:标签;
  • createdAt:添加时间;
  • reviewCount:复习次数;
  • mastered:是否掌握。

这些字段不仅能展示单词详情,也能和复习系统、统计系统结合。

三、存储 Key 设计

StorageService.ts中集中管理存储 Key:

constSTORAGE_KEY_CUSTOM_WORDS ='yingyu_custom_words'constSTORAGE_KEY_REVIEW_RECORDS ='yingyu_review_records'constSTORAGE_KEY_DAILY_TASKS ='yingyu_daily_tasks'constSTORAGE_KEY_LEARNING_GOALS ='yingyu_learning_goals'

把 Key 放在统一服务里有两个好处:

  • 避免页面里到处写字符串;
  • 后续迁移数据结构更方便。

四、生成唯一 ID

添加单词时需要生成唯一 ID:

functiongenerateId():string{ returnDate.now().toString(36)+Math.random().toString(36).substring(2,9) }

这是一个轻量方案,适合本地数据。它结合时间戳和随机字符串,在单机使用场景下足够可靠。

五、读取自定义单词

读取逻辑封装在getCustomWords()中:

exportfunctiongetCustomWords():CustomWord[] {try{conststored =AppStorage.get<string>(STORAGE_KEY_CUSTOM_WORDS)if(stored) {returnJSON.parse(stored)asCustomWord[] } }catch(e) {console.error('Failed to load custom words:', e) }return[] }

这里有一个值得保留的习惯:读取失败时返回空数组,而不是让页面崩掉。学习类应用要优先保证可用性。

六、保存自定义单词

保存时把数组序列化成 JSON:

exportfunctionsaveCustomWords(words: CustomWord[]): void {try{AppStorage.setOrCreate(STORAGE_KEY_CUSTOM_WORDS, JSON.stringify(words)) } catch (e) { console.error('Failedtosave custom words:', e) } }

对于小规模本地生词本,JSON 数组足够简单。后续如果数据量上升,可以迁移到数据库或云端同步。

七、添加单词:补齐系统字段

页面提交的只是用户输入字段,真正保存前由服务层补齐 ID、创建时间、复习次数和掌握状态:

exportfunctionaddCustomWord(word: Omit<CustomWord,'id'|'createdAt'|'reviewCount'|'mastered'>):CustomWord{constnewWord:CustomWord= { ...word,id:generateId(),createdAt:newDate().toISOString(),reviewCount:0,mastered:false}constwords =getCustomWords() words.push(newWord)saveCustomWords(words)returnnewWord }

这样页面只关心用户输入,服务层负责数据完整性。

八、更新和删除

更新单词:

exportfunctionupdateCustomWord(id:string,updates: Partial<CustomWord>): boolean { const words = getCustomWords()const index = words.findIndex(w=>w.id===id)if(index !== -1) { words[index]= { ...words[index], ...updates } saveCustomWords(words)returntrue} returnfalse}

删除单词:

exportfunctiondeleteCustomWord(id:string):boolean{constwords =getCustomWords()constfiltered = words.filter(w=>w.id!== id)if(filtered.length!== words.length) {saveCustomWords(filtered)returntrue}returnfalse}

返回boolean可以让页面判断操作是否成功,并显示 Toast 或刷新列表。

九、搜索过滤

搜索逻辑同时支持英文、中文释义和标签:

exportfunctionsearchCustomWords(keyword:string): CustomWord[]{ const words = getCustomWords()const lower = keyword.toLowerCase()return words.filter(w => w.word.toLowerCase().includes(lower)||w.translation.toLowerCase().includes(lower)||w.tags.some(t => t.toLowerCase().includes(lower)) ) }

这种搜索方式对用户很友好:

  • 输入英文可以找到单词;
  • 输入中文可以找到释义;
  • 输入标签可以找到专题词。

十、添加单词表单

CustomWordBook.ets中定义了AddWordSheet子组件,用于处理添加表单。

@Componentstruct AddWordSheet {@Linkvisible: booleanonWordAdded: () => void = () => {}@StatewordText: string =''@Statephonetic: string =''@Statetranslation: string =''@Stateexample: string =''@StatetagsInput: string =''}

这里把表单做成独立子组件,而不是直接放在页面里,可以减少整页重建,也更利于维护。

提交时处理标签:

const tags = this.tagsInput.split(',').map(t => t.trim()).filter(t => t.length>0)

标签支持逗号分隔,适合用户输入“考试, 写作, 高频词”这样的内容。

十一、详情弹窗:WordDetailSheet

项目还实现了单词详情弹窗:

@Componentstruct WordDetailSheet {@Linkvisible: boolean@Propword: CustomWord = { id: '', word: '', translation: '', tags: [], createdAt: '', reviewCount: 0, mastered: false } }

弹窗进入时有缩放和透明度动画:

aboutToAppear() {this.dialogScale =0.88this.dialogOpacity =0animateTo({ duration:260, curve: Curve.EaseOut }, () => {this.dialogScale =1this.dialogOpacity =1}) }

展示内容包括:

  • 单词;
  • 音标;
  • 中文释义;
  • 例句;
  • 标签;
  • 添加时间;
  • 复习次数或掌握状态。

十二、本地持久化的另一层:Preferences 封装

项目中还有YingYuPreferences.ts,用于 Preferences 和 AppStorage 的兜底封装。

exportfunctioninitYingYuUserData(context: common.UIAbilityContext):void{if(pref) {return}try{ pref = preferences.getPreferencesSync(context, {name:'yingyu_user_data_v1'}) }catch(e) {console.error('initYingYuUserData failed:',JSON.stringify(e)) } }

读取时优先 Preferences,失败则回退 AppStorage:

exportfunctionyingyuPrefGet(key:string):string|undefined{if(pref) {constv = pref.getSync(key,'')asstringreturnv.length>0? v :undefined}constfallback =AppStorage.get<string>(key)if(fallback !==undefined&& fallback.length>0) {returnfallback }returnundefined}

这种封装让数据层更稳,也便于后续统一替换存储方案。

十三、小结

本文结合「英语视界 YingYu」项目,拆解了自定义生词本的完整实现:

  • 使用CustomWord描述用户单词;
  • 使用StorageService封装增删改查;
  • 使用 JSON + AppStorage 保存轻量数据;
  • 使用searchCustomWords()支持英文、中文、标签搜索;
  • 使用AddWordSheet管理添加表单;
  • 使用WordDetailSheet展示单词详情;
  • 使用 Preferences 封装增强持久化可靠性。

自定义生词本让学习 App 从“固定内容工具”变成“用户自己的学习资料库”。这类功能虽然不 flashy,但非常能提升长期使用价值。📖

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 1:54:06

yarn 的单作业运行模式

1.yarn会话模式的管理 #查看yarn应用的日志 yarn logs -applicationId application_1782739955886_0005 |less #查看的结果如下; Container: container_e02_1782739955886_0005_01_000002 on hadoop001_35005 LogAggregationType: AGGREGATEDLogType:directory.info LogL…

作者头像 李华
网站建设 2026/7/2 1:48:00

在以往的项目开发中,在很多地方用到了多线程。

导出文件的示例工具类首先提供一个工具类&#xff0c;用于将指定范围的数字写入txt文件。#ifndef UTILITIES_H #define UTILITIES_H#include <QString> #include <QFile> #include <QTextStream> #include <QDateTime> #include <QDir> #include…

作者头像 李华
网站建设 2026/7/2 1:46:42

HBM吸走产能,东芯股份的SLC NAND开始涨价

AI存储的热门产品是HBM&#xff0c;但一轮由HBM引发的涨价&#xff0c;正在出现在另一类成熟存储芯片上。海外存储厂商把生产资源转向3D NAND和HBM&#xff0c;并逐步退出2D NAND市场&#xff0c;SLC NAND供应随之收缩。东芯股份在2026年6月16日披露的投资者关系活动记录表中表…

作者头像 李华
网站建设 2026/7/2 1:45:54

RAII 有什么作用

RAII 的作用主要体现在&#xff1a;自动资源管理&#xff0c;异常安全&#xff0c;简化代码&#xff0c;提高可维护性。 自动资源管理 获取资源后交由 RAII 类保管&#xff0c;离开作用域后资源被妥善释放&#xff0c;减少手动资源管理容易出现的忘记释放和重复释放。 异常安…

作者头像 李华
网站建设 2026/7/2 1:45:45

后台状态巡检低效怎么排查:状态字段、截图证据和任务日志设计

很多团队都有一类重复任务&#xff1a; 每天打开多个后台页面&#xff0c;检查状态是否正常&#xff0c;确认有没有异常提示&#xff0c;再把结果发到群里或写进表格。 刚开始&#xff0c;这种方式能跑起来。 但后台数量变多、参与人员变多、检查频率变高以后&#xff0c;问…

作者头像 李华
网站建设 2026/7/2 1:42:35

电子自旋的诡异之谜破解 —— 原创电子结构理

百年量子难题&#xff1a;电子自旋始终是物理学 “悬案” 从反常塞曼效应被发现至今&#xff0c;电子自旋已经困扰物理学界百年。现有量子力学体系仅将1/2 自旋简单定义为电子无法解释的 “内禀固有属性”&#xff0c;直接回避自旋的物理起源、微观结构与动力学成因&#xff0…

作者头像 李华