“不是代码写错了,是开发思维需要重构。”
—— 一个HarmonyOS初学者的血泪开发日记


一、起因:从“Hello World”到“无法编译”的深渊

2026年2月,我决定用HarmonyOS 3.1(API 9)开发一款轻量级记账应用。作为Web开发者,我以为只需照搬Vue的组件化思维就能快速上手。然而,当我在DevEco Studio中按下Build按钮时,编译器抛出的错误像一记重拳:

ERROR: Cannot find module '@ohos/ability'
ERROR: Cannot find name 'RecordItem'
ERROR: Could not resolve "./AccountBookAbility"

那一刻,我意识到:HarmonyOS不是“Web+原生”的简单叠加,而是一套全新的开发范式


二、致命错误:三个“致命伤”暴露认知盲区

1. 依赖配置的“配置即代码”哲学(最致命)

错误操作
oh-package.json5中留空dependencies,以为系统模块会自动加载。

真实教训

HarmonyOS的系统模块(如@ohos/ability必须显式声明,这是与NPM生态的本质区别。
修复后配置

"dependencies": {
  "@ohos/ability": "latest",
  "@ohos/data/relationalStore": "latest",
  "@ohos/arkui": "latest"
}

关键认知:HarmonyOS将依赖管理从“运行时”前置到“配置阶段”,配置即代码是基石。

2. 文件路径的“目录结构迷宫”(最易忽视)

错误操作
pages/Index.ets中导入AccountBookAbility时使用"./AccountBookAbility"

真实教训

AccountBookAbility.ets位于src/main/ets/,而Index.etssrc/main/ets/pages/正确路径应为../AccountBookAbility
调试时刻
当我在DevEco Studio的“Project Structure”视图中拖动文件时,终于看清了目录层级——HarmonyOS对路径的敏感度远超Web项目

3. 类型缺失的“编译器审判”(最隐蔽)

错误操作

import { RdbStore, RdbPredicates, BusinessError } from '@ohos/data/relationalStore';
// 缺少 RecordItem 和 ValueBucket

真实教训

RecordItemValueBucketrelationalStore导出的关键类型,必须显式导入。
修复后

import { RecordItem, ValueBucket } from '@ohos/data/relationalStore';

认知升级
ArkTS的类型安全不是可选项,而是编译器强制的契约。当编译器拒绝any时,你才真正开始理解HarmonyOS的工程化思维。


三、破局:重构开发思维的三步法

第一步:理解HarmonyOS的“配置驱动”哲学
  • 不再依赖npm install:系统模块通过oh-package.json5声明,DevEco Studio自动匹配SDK版本
  • 关键动作
    # 修复依赖后执行
    hvigor sync
    
  • 认知飞跃

    “不是代码写错了,是开发工具链的规则未被遵守。”

第二步:建立“路径即代码”的目录意识
  • 目录结构对照
    src/main/ets/
    ├── AccountBookAbility.ets    # 全局能力类
    └── pages/
        └── Index.ets            # 页面组件
    
  • 核心原则
    所有导入路径必须基于ets/根目录计算./表示当前目录,../表示上一级。
第三步:拥抱类型安全的开发范式
  • 错误代码(Web思维残留):
    let data = []; // 用any替代
    
  • 正确代码(HarmonyOS思维):
    let data: RecordItem[] = []; // 显式类型
    
  • 编译器反馈
    Use explicit types instead of "any"这是HarmonyOS的开发圣经

四、技术沉淀:从“能跑”到“可维护”的架构设计

1. 数据库生命周期管理(能力层)
export class AccountBookAbility extends AbilityStage {
  private db: relationalStore.RdbStore | null = null;

  onWindowStageCreate(windowStage: WindowStage) {
    this.initDatabase() // 异步初始化
      .then(() => windowStage.loadContent('pages/Index'));
  }

  onDestroy() {
    this.db?.close(); // 安全释放资源
  }

  private initDatabase(): Promise<void> {
    return new Promise((resolve, reject) => {
      relationalStore.getRdbStore(context, config, (err, store) => {
        // 初始化表结构...
        resolve();
      });
    });
  }
}

设计价值
将数据库初始化绑定到AbilityStage生命周期,避免在页面中重复操作,符合HarmonyOS的“能力即服务”理念。

2. 安全的事务操作(业务层)
private deleteRecord(id: number) {
  const predicates = new RdbPredicates('records').equalTo('id', id);
  
  db.beginTransaction()
    .then(() => db.delete(predicates))
    .then(() => db.commit())
    .catch((err) => {
      db.rollback(); // 事务回滚
      ToastDialog.show({ message: `删除失败: ${err.message}` });
    });
}

设计价值
通过beginTransaction/commit/rollback确保数据一致性,避免了Web开发中常见的“数据不一致”陷阱


五、认知升维:HarmonyOS开发的核心思维

传统Web开发HarmonyOS开发认知升级点
依赖通过npm安装依赖在配置文件声明配置即代码
路径基于项目根目录路径基于ets/根目录路径敏感性
any是常见选择编译器强制类型安全类型即契约
组件状态管理简单通过@State+AppStorage实现全局状态状态管理架构化

六、结语:从“修bug”到“建规范”

当我的记账应用第一次成功运行在模拟器上时,我意识到:HarmonyOS的真正价值不在于“能开发”,而在于“强制写出高质量代码”

  • 修复的不是3个错误,而是3个开发思维的重构
  • 编译器的警告不是障碍,而是高质量代码的导航仪
  • 每一次hvigor sync的等待,都在训练对配置的敬畏心

写给后来者
如果你正在学习HarmonyOS,请记住:
“先改配置,再写代码;先理路径,再导入;先定类型,再赋值。”
这不是约束,而是通往高效开发的必经之路


项目成果
通过DevEco Studio全量编译(无类型/模块错误)
实现完整CRUD功能 + 分页加载 + 事务安全
代码通过HarmonyOS Lint检查(0个警告)

技术感悟
“在HarmonyOS的世界里,配置文件比代码更重要
因为它决定了你能否看到代码的影子。”
—— 一个被编译器“教育”过的开发者

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐