OpenHarmony 完整项目工程整合规范 + 模块化分层架构(API23+ 标准企业级结构)

摘要

前面系列教程覆盖了 ArkUI 组件、路由、生命周期、本地存储、网络请求、Ability 底层全套基础能力,本篇统一梳理标准工程目录分层、模块化拆分、代码复用规范、全局工具统一管理、项目打包权限配置、常见工程报错统一解决方案,形成可直接用于课程设计、实训、小型商业项目的标准化架构,解决新手代码杂乱、工具类分散、状态管理混乱、资源无统一管理等问题。API23 对工程模块导入、上下文传递、文件引用路径有严格校验,不规范目录会出现编译爆红、上下文丢失、存储初始化失败等问题。本文给出固定目录结构、分层职责、统一导入规范、全局初始化流程、完整 module.json5 配置模板,实现低耦合、易维护的鸿蒙应用工程架构。

关键词

OpenHarmony;API23;工程架构;模块化分层;目录规范;工具类统一管理;项目整合;module.json5 配置

一、标准工程整体分层思想(四层架构)

四层分层职责

  1. 底层工具层 utils:网络、数据库、本地存储、路由、弹窗工具,纯逻辑无 UI,全局复用
  2. 数据管理层 model:数据实体类、接口返回类型、全局状态常量、枚举定义
  3. 组件公共层 components:自定义通用 UI 组件(弹窗、输入框、列表项、加载框)
  4. 业务页面层 pages:各功能业务页面,仅负责 UI 渲染与调用上层工具,不写底层原生 API

分层核心原则:单向依赖pages → components → model → utils 禁止反向依赖(工具类不能导入页面、组件),避免循环导入编译报错。

二、API23 标准完整目录结构(entry 模块)

plaintext

entry/src/main/ets ├─ entryability # 应用入口UIAbility,全局生命周期、初始化 │ └─ EntryAbility.ets ├─ pages # 所有业务页面,按功能分文件夹 │ ├─ index # 首页 │ │ └─ Index.ets │ ├─ login # 登录页 │ │ └─ Login.ets │ ├─ mine # 个人中心 │ │ └─ Mine.ets │ ├─ note # 笔记管理 │ │ └─ NoteList.ets │ └─ setting # 设置页 │ └─ Setting.ets ├─ components # 全局通用自定义组件 │ ├─ LoadingDialog.ets # 全局加载弹窗 │ ├─ InputDialog.ets # 输入弹窗 │ └─ NoteItem.ets # 笔记列表条目组件 ├─ model # 数据模型、类型、常量、枚举 │ ├─ Constant.ets # 全局常量(域名、key、页面路由地址) │ ├─ NoteModel.ets # 笔记实体类 │ └─ UserModel.ets # 用户信息实体 ├─ utils # 底层工具类,全局单例 │ ├─ http_util.ets # 网络请求封装 │ ├─ preference_utils.ets # Preferences持久化 │ ├─ rdb_util.ets # RDB数据库工具 │ └─ router_util.ets # 路由跳转工具 └─ resources # 图片、字符串、颜色资源

三、各分层完整代码模板整合

3.1 model 全局常量 Constant.ets(统一管理地址、存储 key)

ets

// 接口基础域名 export const BASE_URL = "https://jsonplaceholder.typicode.com" // AppStorage全局key常量,避免字符串硬编码 export const STORAGE_KEY = { DARK_MODE: "darkMode", IS_LOGIN: "isLogin", USER_NAME: "userName", TOKEN: "token" } // Preferences本地存储key export const PREF_KEY = { DARK_MODE: "dark_mode", LOGIN_ACCOUNT: "login_account", SEARCH_HISTORY: "search_history" } // 页面路由地址统一常量 export const PAGE_ROUTE = { INDEX: "pages/index/index", LOGIN: "pages/login/login", MINE: "pages/mine/mine", NOTE_LIST: "pages/note/NoteList" }

3.2 model 实体类 NoteModel.ets

ets

export interface NoteItem { id: number title: string content: string create_time: number }

3.3 utils 全部工具类(前文整合单例,统一导出无循环依赖)

不再重复粘贴,统一调用规则:

ets

// 页面统一导入方式 import HttpUtil from '../utils/http_util' import PrefUtil from '../utils/preference_utils' import RdbUtil from '../utils/rdb_util' import RouterUtil from '../utils/router_util' import { PAGE_ROUTE, STORAGE_KEY } from '../model/Constant'

3.4 components 通用弹窗 / 条目组件

所有自定义弹窗、复用组件统一放此目录,页面直接导入使用,减少页面冗余代码。

3.5 entryability EntryAbility.ets(全局唯一初始化入口)

整合全套初始化逻辑:

  1. 应用创建初始化 AppStorage 默认值
  2. 窗口创建获取全局上下文,初始化 Preferences、RDB
  3. 前后台自动保存配置、启停全局定时器
  4. 窗口销毁统一关闭数据库、清除定时资源

完整模板见上一篇 Ability 文档,直接复制使用。

3.6 pages 业务页面标准模板(统一规范)

所有页面固定四段式结构:

  1. 顶部导入:工具、模型、组件、常量
  2. @State 页面私有状态
  3. 生命周期:aboutToAppear 加载数据;aboutToDisappear 释放页面资源
  4. build 仅 UI 渲染,无业务逻辑、网络请求

示例标准页面骨架:

ets

import HttpUtil from '../utils/http_util' import RdbUtil from '../utils/rdb_util' import { NoteItem } from '../model/NoteModel' import NoteItem from '../components/NoteItem' @Entry @Component struct NoteList { @State noteList: NoteItem[] = [] timer: number | null = null requestCancel: boolean = false async aboutToAppear() { this.requestCancel = false await RdbUtil.init(getContext(this)) await this.loadData() // 页面局部定时器 this.timer = setInterval(()=>{}, 10000) } // 业务方法:仅调用工具层,不写原生API async loadData() { const list = await RdbUtil.queryNoteList(0,10) if(!this.requestCancel) this.noteList = list } build() { List({space:12}) { ForEach(this.noteList, item => { ListItem() { NoteItem({data: item}) } }) } } aboutToDisappear() { // 页面资源释放 this.requestCancel = true if(this.timer) clearInterval(this.timer) RdbUtil.closeDB() } }

四、全局统一初始化完整流程(应用启动全链路)

  1. 冷启动:点击桌面图标 → EntryAbility.onCreate
    • 初始化 AppStorage 全部全局默认 key
  2. onWindowStageCreate
    • 获取全局上下文 context,传入 Pref、RDB 工具初始化
    • 读取本地 Preferences 配置,覆盖 AppStorage 全局状态
    • loadContent 加载首页 pages/index
  3. 首页 Index 页面 aboutToAppear
    • 按需拉取首页网络数据、加载列表
  4. 切后台 onBackground
    • 暂停全局定时器,将 AppStorage 配置同步写入 Preferences
  5. 切前台 onForeground
    • 重启全局定时轮询,刷新首页数据
  6. 退出应用 / 全部页面关闭 onWindowStageDestroy
    • 清除全局定时器、关闭 RDB 数据库,释放全部重量级资源

五、module.json5 全套基础配置(API23 必备)

5.1 网络权限、页面注册、窗口配置

json

{ "module": { "name": "entry", "type": "entry", "description": "$string:module_desc", "main": "entryability/EntryAbility", "deviceTypes": ["phone"], "deliveryWithInstall": true, "installationFree": false, "pages": [ "pages/index/index", "pages/login/login", "pages/mine/mine", "pages/note/NoteList", "pages/setting/Setting" ], "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ], "window": { "designWidth": 720, "autoDesignWidth": true } } }

5.2 明文 HTTP 白名单配置(仅测试使用)

项目目录entry/ohos.security.json5

json

{ "network": { "cleartextTraffic": true } }

六、API23 工程开发强制编码规范

6.1 导入与路径规范

  1. 全部使用相对路径../导入,禁止绝对路径
  2. 工具类统一单例导出:export default xxxUtil
  3. 常量、类型使用命名导出:export const / export interface
  4. 禁止页面之间互相导入(页面跳转只用 router,不直接引入页面组件)

6.2 状态分层规范

  1. 全局共享数据:AppStorage + Preferences 持久化
  2. 页面独立临时数据:页面内部 @State
  3. 弹窗临时数据:弹窗内部 @State
  4. 常量、接口地址统一放入 model/Constant,禁止页面写死字符串

6.3 资源释放统一规范

  1. 应用全局资源(数据库、全局定时器):EntryAbility 生命周期销毁
  2. 页面局部定时器、网络请求:页面 aboutToDisappear 销毁
  3. 弹窗临时资源:CustomDialog 自身 aboutToDisappear 销毁

6.4 网络、存储调用规范

  1. 禁止页面直接导入原生 http /preferences/relationalStore
  2. 所有读写操作统一调用 utils 封装工具类,统一拦截错误、加载弹窗
  3. 数据库操作统一单例工具,避免多实例文件占用报错

6.5 UI 组件复用规范

  1. 重复列表条目、弹窗、按钮卡片抽取至 components
  2. 页面仅组装业务,复杂 UI 拆分自定义组件,降低页面代码量

七、API23 工程高频编译报错与一次性解决方案

  1. 循环导入报错原因:页面导入组件,组件又导入页面;工具类导入页面 解决:严格单向分层,utils、model 不导入页面与 components

  2. Preferences/RDB 初始化上下文为空原因:页面过早调用工具 init,未等 Ability 创建窗口 解决:统一在 EntryAbility.onWindowStageCreate 传入全局 context 初始化

  3. http 明文接口 404 / 请求无响应解决:配置 ohos.security.json5 开启 cleartextTraffic,线上全部替换 https

  4. 页面跳转 getParams 读取参数为空解决:使用 RouterUtil 标准封装 pushUrl,完整传入 params 对象,不简写 url 字符串

  5. 数据库文件被占用,多次进出页面报错解决:页面 aboutToDisappear 调用 RdbUtil.closeDB,全局单例复用

  6. 页面退出后网络请求回调修改状态,控制台报错解决:页面增加 requestCancel 标记,aboutToDisappear 置 true,回调赋值前判断

  7. 弹窗多次打开保留上次输入内容解决:弹窗 aboutToAppear 重置内部 @State 输入变量

八、完整项目开发执行流程(课程设计 / 毕设标准步骤)

  1. 搭建标准四层目录结构(utils/model/components/pages/entryability)
  2. 编写 model 常量、实体类型,统一管理路由、存储 key、接口域名
  3. 封装全套 utils 工具:http、preference、rdb、router
  4. 编写通用 components 弹窗、列表条目组件
  5. 完善 EntryAbility 全局初始化、前后台资源管控逻辑
  6. 按业务开发 pages 页面,遵循标准页面模板
  7. 配置 module.json5 页面、网络权限、窗口适配
  8. 联调:登录持久化、全局主题、笔记数据库增删改查、页面路由跳转
  9. 统一处理加载弹窗、异常 Toast、资源释放、退出清空登录态
  10. 测试多页面切换、后台驻留、重启应用数据持久化校验

九、整套系列教程完整汇总目录

  1. ArkUI 基础布局:Row、Column、Stack、List
  2. 基础 UI 组件:Text、Image、Button、TextInput
  3. 选择交互控件:Toggle、Radio、Checkbox、Slider
  4. 自定义弹窗 CustomDialog
  5. 全局状态 AppStorage
  6. 本地轻量持久化 Preferences
  7. 关系型数据库 RDB(海量结构化数据)
  8. Router 页面路由与跨页面传参
  9. 页面 & 组件生命周期 aboutToAppear/aboutToDisappear
  10. Http 网络请求全局封装
  11. UIAbility 应用底层生命周期
  12. 本篇:API23 标准模块化工程整合架构