【OpenHarmony/HarmonyOs 】HarmonyOS NEXT 学习类 App 项目架构拆解:页面、数据、主题与工具层

当一个 ArkTS 项目页面越来越多时,架构就会变得很重要。代码如果只按页面堆叠,后期会很难维护。本文结合 政治视界 项目,拆解一个 HarmonyOS NEXT 学习类 App 的项目结构和模块职责 🧩

一、项目整体结构

项目核心目录如下:

entry/src/main/ets/
├── pages/
│   ├── Index.ets
│   ├── HomePage.ets
│   ├── QuizPage.ets
│   ├── NotesPage.ets
│   ├── FlashCardPage.ets
│   ├── NewspaperPage.ets
│   ├── DailyPoliticsPage.ets
│   ├── ProfilePage.ets
│   └── StatsPage.ets
├── data/
│   ├── SampleData.ets
│   └── NewspaperData.ets
├── model/
│   └── DataModel.ets
├── common/
│   ├── AppTheme.ets
│   ├── ResponsiveUtils.ets
│   └── AppLocalStorage.ets
├── components/
│   └── AppBackground.ets
└── utils/
    ├── DataManager.ets
    └── StorageManager.ets

这个结构分层比较清楚:页面、数据、模型、公共工具、组件、业务管理各有位置。

二、页面层 pages

pages 负责用户界面和交互:

  • Index.ets:底部 Tab 主框架;
  • HomePage.ets:学习首页看板;
  • QuizPage.ets:题库练习;
  • NotesPage.ets:笔记;
  • FlashCardPage.ets:闪卡;
  • NewspaperPage.ets:政治报纸;
  • ProfilePage.ets:我的、目标、成就;
  • StatsPage.ets:学习报告。

页面层不应该直接写底层存储逻辑,而应该调用 DataManager

三、模型层 model

DataModel.ets 定义项目中所有核心数据结构:

export interface Question {
  id: number;
  category: string;
  grade: string;
  knowledgePoint: string;
  type: 'single' | 'multiple' | 'truefalse' | 'fill';
  question: string;
  answer: string | string[];
}

模型统一后,页面和数据管理层就有共同语言。比如题库页面、错题记录、首页推荐都使用同一个 Question 类型。

四、数据层 data

SampleData.etsNewspaperData.ets 保存内置学习内容:

export const sampleQuestions: Question[] = [
  {
    id: 1,
    category: '经济',
    grade: '高一',
    knowledgePoint: '公有制经济',
    type: 'single',
    question: '下列属于公有制经济的是()',
    answer: 'C',
    difficulty: 1
  }
];

项目早期使用静态数据非常合适,方便调试页面和交互。后续可以替换为接口或数据库。

五、业务管理层 DataManager

DataManager 是项目的数据中枢,负责:

  • 学习统计;
  • 错题记录;
  • 学习会话;
  • 每日目标;
  • 成就系统;
  • 用户信息;
  • 设置数据。

例如答题记录:

recordAnswer(question: Question, userAnswer: string, isCorrect: boolean): void {
  this.studyStats.completedQuestions++;
  if (isCorrect) {
    this.studyStats.correctCount++;
  }
  if (!isCorrect) {
    this.addWrongQuestion(question, userAnswer);
  }
  this.saveStats();
}

页面只调用这个方法,不关心内部怎么保存。

六、存储层 StorageManager

StorageManager 封装 Preferences:

async init(context: common.UIAbilityContext): Promise<void> {
  if (this.prefs !== null) {
    return;
  }
  this.prefs = await preferences.getPreferences(context, PREFERENCES_NAME);
}

它只负责读写键值,不处理业务。这种分层让代码更稳定。

七、公共能力 common

common 目录放跨页面复用能力:

  • AppTheme:主题色;
  • ResponsiveUtils:响应式布局;
  • AppLocalStorage:全局状态;
  • SafeAreaKeys:安全区 key。

比如页面使用主题色:

.backgroundColor(AppTheme.cardBg)
.fontColor(AppTheme.titlePrimary)

这样页面样式统一,维护成本低。

八、组件层 components

当前项目中有 AppBackground

@Component
export struct AppBackground {
  @Prop showDecorations: boolean = true;

  build() {
    Stack() {
      // 全局背景
    }
  }
}

背景作为组件抽离后,每个页面都可以复用,不需要重复写背景逻辑。

九、主框架 Index

Index.ets 是一级页面容器,管理底部 Tab 和页面切换:

if (this.currentTab === 0) {
  HomePage({ currentTab: $currentTab, refreshSignal: $homePageRefresh })
} else if (this.currentTab === 1) {
  NewspaperPage()
} else if (this.currentTab === 2) {
  NotesPage()
}

主框架负责导航,子页面负责自己的内容,这个边界很清楚。

十、架构总结

EntryAbility
  ↓ 初始化存储/窗口
Index
  ↓ Tab 容器
pages
  ↓ 调用
DataManager
  ↓ 调用
StorageManager
  ↓ Preferences

十一、结语

政治视界的架构适合中小型学习 App:页面清晰、模型统一、数据集中管理、主题和响应式能力抽离。这样的结构后续扩展新页面也比较顺,比如增加模拟考试、隐私设置、学习计划页面,都能放进现有架构。

好的项目结构不是为了看起来高级,而是为了让功能越多时代码仍然可控 🚀

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐