摘要

前面系列教程覆盖了 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 标准模块化工程整合架构
Logo

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

更多推荐