当前位置: 首页 > news >正文

HarmonyOS APP<玩转React>开源教程六:数据模型设计与实现

第6次:数据模型设计与实现

数据模型是应用的骨架,定义了数据的结构和类型。本次课程将深入设计 React 学习教程 App 的完整数据模型,为后续功能开发奠定基础。


学习目标

  • 理解数据模型设计原则
  • 掌握学习模块数据结构设计
  • 设计课程内容数据结构
  • 实现用户进度数据模型
  • 完成测验相关数据模型
  • 编写完整的 Models.ets 文件

效果

6.1 数据模型设计原则

设计原则

  1. 单一职责:每个接口只描述一种数据
  2. 类型安全:使用明确的类型,避免 any
  3. 可扩展性:预留扩展空间
  4. 一致性:命名和结构保持一致
  5. 文档化:添加清晰的注释

命名规范

// 接口:名词,PascalCaseinterfaceLearningModule{}interfaceUserProgress{}// 类型别名:描述性名称typeDifficultyType='beginner'|'basic'|'intermediate';typeCodeLanguage='javascript'|'typescript';// 常量:UPPER_SNAKE_CASEconstDEFAULT_USER_PROGRESS:UserProgress={};

6.2 学习模块数据结构

模块层级关系

App └── LearningModule (学习模块) └── Lesson (课程) └── LessonContent (课程内容) ├── ContentSection (内容段落) ├── CodeExample (代码示例) └── TOCItem (目录项)

LearningModule 接口

/** * 学习模块 * 代表一个完整的学习单元,如"React 简介"、"Hooks 基础" */exportinterfaceLearningModule{/** 模块唯一标识 */id:string;/** 模块标题 */title:string;/** 模块描述 */description:string;/** 难度等级 */difficulty:DifficultyType;/** 图标(emoji 或图片路径) */icon:string;/** 主题色 */color:string;/** 课程数量 */lessonCount:number;/** 预计学习时间 */estimatedTime:string;/** 前置模块 ID 列表 */prerequisites:string[];/** 课程列表 */lessons:Lesson[];}

Lesson 接口 课程接口

/** * 课程 * 模块下的具体课程单元 */exportinterfaceLesson{/** 课程唯一标识 */id:string;/** 所属模块 ID */moduleId:string;/** 课程标题 */title:string;/** 课程描述 */description:string;/** 排序序号 */order:number;/** 课程内容 */content:LessonContent;/** 是否有代码练习 */hasPlayground:boolean;/** 是否有测验 */hasQuiz:boolean;}

难度类型定义

/** * 难度等级类型 */exporttypeDifficultyType=|'beginner'// 入门|'basic'// 基础|'intermediate'// 进阶|'advanced'// 高级|'ecosystem';// 生态

6.3 课程内容数据结构

LessonContent 接口

/** * 课程内容 * 包含课程的所有内容元素 */exportinterfaceLessonContent{/** 内容段落列表 */sections:ContentSection[];/** 代码示例列表 */codeExamples:CodeExample[];/** 目录 */tableOfContents:TOCItem[];/** 关键要点 */keyTakeaways:string[];}

ContentSection 接口

/** * 内容段落类型 */exporttypeSectionType=|'text'// 普通文本|'code'// 代码块|'tip'// 提示|'warning'// 警告|'note';// 注释/** * 内容段落 */exportinterfaceContentSection{/** 段落 ID */id:string;/** 段落标题 */title:string;/** 段落内容 */content:string;/** 段落类型 */type:SectionType;}

CodeExample 接口

/** * 代码语言类型 */exporttypeCodeLanguage=|'javascript'|'typescript'|'jsx'|'tsx'|'css'|'json'|'bash'|'html'|'text';/** * 代码示例 */exportinterfaceCodeExample{/** 示例 ID */id:string;/** 示例标题 */title:string;/** 代码内容 */code:string;/** 代码语言 */language:CodeLanguage;/** 代码解释 */explanation:string;/** 是否可编辑(在调试器中) */isEditable:boolean;}

TOCItem 接口

/** * 目录项 */exportinterfaceTOCItem{/** 目录项 ID */id:string;/** 目录标题 */title:string;/** 层级(1-3) */level:number;}

6.4 用户进度数据模型

UserProgress 接口

/** * 用户进度 * 记录用户的学习状态和成就 */exportinterfaceUserProgress{/** 已完成课程 ID 列表 */completedLessons:string[];/** 已完成模块 ID 列表 */completedModules:string[];/** 当前学习课程 ID */currentLesson:string|null;/** 连续学习天数 */learningStreak:number;/** 最后学习日期(YYYY-MM-DD) */lastStudyDate:string;/** 总学习时长(分钟) */totalStudyTime:number;/** 获得的徽章列表 */badges:Badge[];}/** * 默认用户进度 */exportconstDEFAULT_USER_PROGRESS:UserProgress={completedLessons:[],completedModules:[],currentLesson:null,learningStreak:0,lastStudyDate:'',totalStudyTime:0,badges:[]};

Badge 接口

/** * 徽章类别 */exporttypeBadgeCategory=|'progress'// 进度类|'streak'// 连续学习类|'quiz'// 测验类|'project';// 项目类/** * 成就徽章 */exportinterfaceBadge{/** 徽章 ID */id:string;/** 徽章名称 */name:string;/** 徽章描述 */description:string;/** 徽章图标 */icon:string;/** 获得日期 */earnedDate:string;/** 徽章类别 */category:BadgeCategory;}

Bookmark 接口

/** * 收藏 */exportinterfaceBookmark{/** 课程 ID */lessonId:string;/** 模块 ID */moduleId:string;/** 添加时间 */addedAt:string;}

6.5 测验相关数据模型

Quiz 接口

/** * 测验 */exportinterfaceQuiz{/** 测验 ID */id:string;/** 所属模块 ID */moduleId:string;/** 所属课程 ID(可选) */lessonId?:string;/** 测验标题 */title:string;/** 题目列表 */questions:QuizItem[];/** 及格分数(百分制) */passingScore:number;/** 时间限制(秒,可选) */timeLimit?:number;}

QuizItem 接口

/** * 测验题目 */exportinterfaceQuizItem{/** 题目 ID */id:string;/** 题目内容 */question:string;/** 选项列表(通常 4 个) */options:string[];/** 正确答案索引(0-3) */correctAnswer:number;/** 答案解析 */explanation:string;/** 代码片段(可选) */codeSnippet?:string;}

QuizResult 接口

/** * 测验结果 */exportinterfaceQuizResult{/** 测验 ID */quizId:string;/** 得分(百分制) */score:number;/** 总题数 */totalQuestions:number;/** 是否通过 */passed:boolean;/** 用户答案列表 */answers:number[];/** 完成时间 */completedAt:string;/** 用时(秒) */timeSpent:number;}

面试题相关模型

/** * 面试题难度 */exporttypeInterviewDifficulty='easy'|'medium'|'hard';/** * 面试题目 */exportinterfaceInterviewQuestion{/** 题目 ID */id:string;/** 所属模块 ID */moduleId:string;/** 模块名称 */moduleName:string;/** 题目内容 */question:string;/** 选项列表 */options:string[];/** 正确答案索引 */correctAnswer:number;/** 答案解析 */explanation:string;/** 难度等级 */difficulty:InterviewDifficulty;/** 代码片段(可选) */codeSnippet?:string;}/** * 错题记录 */exportinterfaceWrongAnswerRecord{/** 题目 ID */questionId:string;/** 完整题目信息 */question:InterviewQuestion;/** 用户的错误答案 */userAnswer:number;/** 正确答案 */correctAnswer:number;/** 记录时间 */recordedAt:string;/** 尝试次数 */attemptCount:number;/** 是否已掌握 */isMastered:boolean;/** 最后尝试时间 */lastAttemptAt:string;}/** * 答题统计 */exportinterfaceQuizStatistics{/** 总答题数 */totalAnswered:number;/** 正确数 */correctCount:number;/** 错误数 */wrongCount:number;/** 正确率(0-100) */accuracyRate:number;/** 各模块统计 */moduleStats:Record<string,ModuleQuizStats>;/** 最后更新时间 */lastUpdated:string;}/** * 模块答题统计 */exportinterfaceModuleQuizStats{moduleId:string;moduleName:string;totalQuestions:number;answeredCount:number;correctCount:number;accuracyRate:number;}/** * 默认答题统计 */exportconstDEFAULT_QUIZ_STATISTICS:QuizStatistics={totalAnswered:0,correctCount:0,wrongCount:0,accuracyRate:0,moduleStats:{},lastUpdated:''};

6.6 其他辅助模型

SearchResult 接口

/** * 搜索结果 */exportinterfaceSearchResult{/** 结果类型 */type:'module'|'lesson';/** ID */id:string;/** 标题 */title:string;/** 描述 */description:string;/** 匹配的文本 */matchedText:string;/** 模块 ID(课程结果时) */moduleId?:string;/** 模块标题 */moduleTitle?:string;/** 难度 */difficulty?:DifficultyType;}

DailyQuestion 接口

/** * 每日一题 */exportinterfaceDailyQuestion{/** 日期(YYYY-MM-DD) */date:string;/** 题目 */question:QuizItem;/** 来源模块 ID */moduleId:string;/** 来源课程 ID */lessonId:string;/** 是否已回答 */answered:boolean;/** 是否回答正确 */correct?:boolean;}

6.7 实操:完成 Models.ets 文件

现在,让我们将所有数据模型整合到一个完整的文件中。

更新entry/src/main/ets/models/Models.ets

/** * 数据模型定义 * React 教程应用的所有类型接口 */// ==================== 基础类型 ====================exporttypeDifficultyType='beginner'|'basic'|'intermediate'|'advanced'|'ecosystem';exporttypeCodeLanguage='javascript'|'typescript'|'jsx'|'tsx'|'css'|'json'|'bash'|'html'|'text';exporttypeSectionType='text'|'code'|'tip'|'warning'|'note';exporttypeBadgeCategory='progress'|'streak'|'quiz'|'project';exporttypeInterviewDifficulty='easy'|'medium'|'hard';// ==================== 学习模块 ====================exportinterfaceLearningModule{id:string;title:string;description:string;difficulty:DifficultyType;icon:string;color:string;lessonCount:number;estimatedTime:string;prerequisites:string[];lessons:Lesson[];}exportinterfaceLesson{id:string;moduleId:string;title:string;description:string;order:number;content:LessonContent;hasPlayground:boolean;hasQuiz:boolean;}exportinterfaceLessonContent{sections:ContentSection[];codeExamples:CodeExample[];tableOfContents:TOCItem[];keyTakeaways:string[];}exportinterfaceContentSection{id:string;title:string;content:string;type:SectionType;}exportinterfaceCodeExample{id:string;title:string;code:string;language:CodeLanguage;explanation:string;isEditable:boolean;}exportinterfaceTOCItem{id:string;title:string;level:number;}// ==================== 用户进度 ====================exportinterfaceUserProgress{completedLessons:string[];completedModules:string[];currentLesson:string|null;learningStreak:number;lastStudyDate:string;totalStudyTime:number;badges:Badge[];}exportinterfaceBadge{id:string;name:string;description:string;icon:string;earnedDate:string;category:BadgeCategory;}exportinterfaceBookmark{lessonId:string;moduleId:string;addedAt:string;}exportconstDEFAULT_USER_PROGRESS:UserProgress={completedLessons:[],completedModules:[],currentLesson:null,learningStreak:0,lastStudyDate:'',totalStudyTime:0,badges:[]};// ==================== 测验相关 ====================exportinterfaceQuiz{id:string;moduleId:string;lessonId?:string;title:string;questions:QuizItem[];passingScore:number;timeLimit?:number;}exportinterfaceQuizItem{id:string;question:string;options:string[];correctAnswer:number;explanation:string;codeSnippet?:string;}exportinterfaceQuizResult{quizId:string;score:number;totalQuestions:number;passed:boolean;answers:number[];completedAt:string;timeSpent:number;}exportinterfaceDailyQuestion{date:string;question:QuizItem;moduleId:string;lessonId:string;answered:boolean;correct?:boolean;}// ==================== 面试题库 ====================exportinterfaceInterviewQuestion{id:string;moduleId:string;moduleName:string;question:string;options:string[];correctAnswer:number;explanation:string;difficulty:InterviewDifficulty;codeSnippet?:string;}exportinterfaceWrongAnswerRecord{questionId:string;question:InterviewQuestion;userAnswer:number;correctAnswer:number;recordedAt:string;attemptCount:number;isMastered:boolean;lastAttemptAt:string;}exportinterfaceQuizStatistics{totalAnswered:number;correctCount:number;wrongCount:number;accuracyRate:number;moduleStats:Record<string,ModuleQuizStats>;lastUpdated:string;}exportinterfaceModuleQuizStats{moduleId:string;moduleName:string;totalQuestions:number;answeredCount:number;correctCount:number;accuracyRate:number;}exportconstDEFAULT_QUIZ_STATISTICS:QuizStatistics={totalAnswered:0,correctCount:0,wrongCount:0,accuracyRate:0,moduleStats:{},lastUpdated:''};// ==================== 搜索 ====================exportinterfaceSearchResult{type:'module'|'lesson';id:string;title:string;description:string;matchedText:string;moduleId?:string;moduleTitle?:string;difficulty?:DifficultyType;}

本次课程小结

通过本次课程,你已经:

✅ 理解了数据模型设计原则
✅ 设计了学习模块的完整数据结构
✅ 实现了课程内容的数据模型
✅ 完成了用户进度数据模型
✅ 设计了测验和面试题相关模型
✅ 编写了完整的 Models.ets 文件


课后练习

  1. 扩展模型:为 UserProgress 添加学习目标相关字段

  2. 添加验证:编写函数验证 LearningModule 数据的完整性

  3. 类型守卫:编写类型守卫函数判断对象是否为特定接口类型


下次预告

第7次:本地数据持久化

我们将深入学习数据持久化:

  • Preferences 存储详解
  • StorageUtil 工具类完善
  • 异步存储操作
  • 数据迁移与版本管理

让应用数据能够持久保存!

http://www.jsqmd.com/news/477268/

相关文章:

  • 多模态AI实战:CLIP模型原理与代码深度剖析
  • 基于QWidget创建的自定义窗口在使用isVisible时造成程序崩溃
  • 2026海鲜泡沫箱采购攻略:精选厂家不容错过,国内头部泡沫箱企业排行榜单赋能企业生产效率提升与成本优化 - 品牌推荐师
  • 【最好最全面】openclaw安装方法【教程即时更新,永不过期】
  • CSDN Markdown 微笑与 section 符号
  • 打印机连接故障排除方案
  • SNMP(简单网络管理协议)
  • Python 中通过命令行向函数传参
  • 天津市优秀的GEO生成式AI引擎优化的公司有哪些
  • **WebTransport:下一代低延迟实时通信协议的实战解析与代码实现**
  • LSTM的工作原理
  • 2026年创业热潮来袭,专业创业指导定制公司能否成为TOP选择?
  • 闲置天猫超市卡别等过期!这样处理,安全又省心 - 可可收
  • 第三章 第一性原理:从零到一的完整思考方法论
  • 技术:双电脑共享鼠标、键盘解决方案 | USB对拷线、Synergy
  • 电赛信号题备赛日记(1)移植正点原子STM32H750 mini pro的TFTLCD屏幕
  • 行楷 - 汉字行楷手写体字形
  • 文献汇总|AI生成图像检测与溯源相关工作(2026)
  • Win10 WSL安装Centos7 Nginx+PHP+MySQL
  • 柔性温度传感器--折线型结构
  • Tomcat简单实现
  • 关于学生课堂行为识别算法
  • 微软 GraphRAG从构图到检索的核心逻辑与代码实现
  • 2026年黄铜、不锈钢、钛合金光纤接头精密零件CNC加工厂家权威推荐:这三家凭什么脱颖而出? - 余文22
  • Esri 2020 10m全球土地覆盖数据下载(Land Cover Downloader)
  • Visual Studio - 修改主题背景颜色
  • 衬线字体 (serif) 和无衬线字体 (sans-serif)
  • Flutter 三方库 google_play_scraper 鸿蒙适配指南 - 实现高性能应用商店元数据抓取、在 OpenHarmony 上打造竞品分析数据防御线实战
  • 蜂胶经常吃的品牌是选哪个? 2026年高吸收蜂胶TOP十榜单:10款实测优选! - 博客万
  • Visual Studio - 修改字体