鸿蒙原生应用实战(一):塔罗牌占卜App开发 — 环境搭建与首页开发

鸿蒙原生应用实战(一):塔罗牌占卜App开发 --- 环境搭建与首页开发

前言

随着华为鸿蒙生态的快速发展,越来越多的开发者开始投身鸿蒙原生应用开发。本系列文章将以一个完整的 塔罗牌占卜 App 为案例,从零开始讲解鸿蒙原生应用的完整开发流程。无论你是刚接触鸿蒙开发的新手,还是有一定经验的开发者,都能从中获得实践参考。

本文是第一篇,聚焦于 开发环境搭建、项目初始化、Stage 模型理解以及首页页面的实现。我们将深入探讨鸿蒙开发中的常见问题、最佳实践和性能优化技巧,帮助你在实际项目中少走弯路。

为什么选择塔罗牌 App 作为案例?

  1. 功能全面:包含UI布局、状态管理、路由跳转、主题切换等核心功能
  2. 数据驱动:涉及本地数据存储、随机算法、卡片展示等数据处理逻辑
  3. 组件化:适合展示ArkTS的组件化开发模式
  4. 实用性强:可以扩展为完整的商业化应用
  5. 学习曲线平缓:从简单到复杂,逐步掌握鸿蒙开发技能

本文目标读者:

  • 有一定前端开发经验,想学习鸿蒙原生应用开发
  • 已经了解 TypeScript/JavaScript,想迁移到 ArkTS
  • 希望了解鸿蒙 Stage 模型和组件化开发
  • 需要实战项目经验来巩固理论知识

你将学到:

  • ✅ 鸿蒙开发环境搭建与配置
  • ✅ Stage 模型的核心概念与应用
  • ✅ ArkTS 语言特性与开发规范
  • ✅ 响应式 UI 设计与状态管理
  • ✅ 路由导航与页面跳转
  • ✅ 主题切换与国际化支持
  • ✅ 性能优化与调试技巧

前置知识要求:

  • 基本的 TypeScript/JavaScript 语法
  • 了解面向对象编程概念
  • 熟悉常见的 UI 布局原理
  • 有任一前端框架(Vue/React/Angular)使用经验更佳

让我们开始鸿蒙原生应用开发之旅吧!

---## 一、开发环境搭建

1.1 DevEco Studio 安装

鸿蒙应用开发的首选 IDE 是 DevEco Studio(基于 IntelliJ IDEA 定制)。前往华为开发者官网下载最新版本。

当前版本 : DevEco Studio 5.0+

SDK 版本: API 23 (HarmonyOS 6.1.0)

1.2 项目配置要点

创建项目时,有几个关键配置值得注意:

json 复制代码
// build-profile.json5 (项目级)
{
  "app": {
    "products": [
      {
        "name": "default",
        "targetSdkVersion": "6.1.1(24)",
        "compatibleSdkVersion": "6.1.0(23)",
        "runtimeOS": "HarmonyOS"
      }
    ]
  }
}
  • compatibleSdkVersion: 最低兼容版本,设为 23 可覆盖大部分设备
  • targetSdkVersion: 目标 SDK 版本,设为 24 可使用最新的 API
  • runtimeOS: 指定运行 OS 为 HarmonyOS

1.3 @kit.AbilityKit 路由的坑

在 API 23 中,router 模块应通过 @ohos.router 导入,而不是 @kit.AbilityKit

typescript 复制代码
// ✅ 正确导入方式
import router from '@ohos.router';

// ❌ 错误:API 23 不导出 @kit.AbilityKit 的 router
// import { router } from '@kit.AbilityKit';

这是一个容易踩坑的地方,API 版本不同,导入路径差异很大。


二、项目结构设计

2.1 Stage 模型概述

鸿蒙应用有两种模型:FA(Feature Ability)模型Stage 模型 。本项目采用 Stage 模型,它是鸿蒙从 API 9 开始推荐的新模型,具有以下优势:

  • 组件化设计,Ability 和 UI 分离
  • 更清晰的生命周期管理
  • 更好的跨设备迁移支持

2.2 目录结构规划

复制代码
MyApplication/
├── AppScope/                    ← 全局应用配置
│   ├── app.json5                ← 应用级配置(bundleName、版本等)
│   └── resources/               ← 全局资源
│       └── base/element/string.json
├── entry/                       ← 主模块
│   └── src/main/
│       ├── ets/
│       │   ├── entryability/    ← Ability 入口
│       │   ├── model/           ← 数据模型层
│       │   └── pages/           ← 页面层
│       ├── module.json5         ← 模块配置
│       └── resources/           ← 模块级资源
├── build-profile.json5          ← 构建配置
└── hvigor/                      ← 构建工具配置

2.3 路由注册

页面路由需要在 main_pages.json 中注册:

json 复制代码
// resources/base/profile/main_pages.json
{
  "src": [
    "pages/Index",
    "pages/CardListPage",
    "pages/CardDetailPage",
    "pages/SpreadPage",
    "pages/FavPage"
  ]
}

而在 module.json5 中通过 $profile:main_pages 引用:

json 复制代码
{
  "module": {
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets"
      }
    ]
  }
}

三、Ability 入口:程序启动的地方

EntryAbility.ets 是整个应用的入口。它的核心职责是加载首页页面:

typescript 复制代码
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load: %{public}s', JSON.stringify(err));
        return;
      }
      // 加载成功
    });
  }
}

这里有一个小技巧:通过 this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET) 可以禁止系统跟随深色模式,让 App 自主控制主题。


四、首页(Index.ets)完整实现

首页是整个 App 的门面。我们的塔罗牌 App 首页需要包含:

  1. 顶部品牌区:Logo、标题、主题切换按钮
  2. 今日塔罗:随机抽牌展示,点击可再抽
  3. 功能导航:三个入口卡片(全部牌义、牌阵解读、我的收藏)

4.1 首页布局结构

typescript 复制代码
@Entry
@Component
struct Index {
  @State todayCard: TarotCard = TAROT_CARDS[0];
  @State showCard: boolean = false;
  @State theme: ThemeColors = ThemeManager.colors;

  build() {
    Column() {
      // 顶部标题区
      Column() { /* Logo + 标题 + 主题切换 */ }
      
      Scroll() {
        Column() {
          // 今日塔罗模块
          // 功能导航入口
        }
      }
    }
  }
}

这里有一个重要的 ArkTS 语法特性:@State 装饰器 。被 @State 修饰的变量发生改变时,UI 会自动刷新。ArkTS 的响应式机制与 Vue 的 ref / reactive 类似,但更加轻量。

4.2 今日塔罗抽牌逻辑

typescript 复制代码
drawTodayCard(): void {
  const index = Math.floor(Math.random() * TAROT_CARDS.length);
  this.todayCard = TAROT_CARDS[index];
  this.showCard = true;
}

抽牌前显示一个带"?"的卡片,点击后通过随机数从塔罗牌数组中抽取一张,显示牌名、关键词和简要释义。点击卡片可跳转到详情页。

4.3 主题切换

通过点击月亮/太阳图标切换深色/浅色主题:

typescript 复制代码
toggleTheme(): void {
  ThemeManager.toggle();          // 切换主题
  this.theme = ThemeManager.colors; // 更新本地状态触发 UI 刷新
}

4.4 组件化:提取 EntryCard

ArkTS 支持类似 React 的组件化开发,我们可以将功能导航卡片提取为独立组件:

typescript 复制代码
@Component
struct EntryCard {
  icon: string = '';
  title: string = '';
  desc: string = '';
  onTap?: () => void;
  theme: ThemeColors = DARK_MYSTIC;

  build() {
    Row() {
      Text(this.icon).fontSize(32);
      Column() {
        Text(this.title).fontWeight(FontWeight.Bold);
        Text(this.desc).fontColor(this.theme.textSecondary);
      }
      Text('›').fontColor(this.theme.textSecondary);
    }
    .onClick(() => { if (this.onTap) { this.onTap(); } });
  }
}

使用方式:

typescript 复制代码
EntryCard({
  icon: '📖',
  title: '全部牌义',
  desc: '大阿卡纳 · 小阿卡纳 详解',
  onTap: () => { router.pushUrl({ url: 'pages/CardListPage' }); },
  theme: this.theme
});

五、ArkTS 开发注意事项

5.1 严格模式下的类型约束

ArkTS 在严格模式下有以下限制(这是与标准 TypeScript 最大的区别):

对象字面量必须有显式类型声明 (规则: arkts-no-untyped-obj-literals):

typescript 复制代码
// ❌ 错误写法
const result = [{ name: '愚者', id: 0 }];

// ✅ 正确写法:先定义类型,再赋值
const arr: TarotCard[] = [];
arr.push({ id: 0, name: '愚者', ... });

数组字面量必须可推断类型 (规则: arkts-no-noninferrable-arr-literals):

typescript 复制代码
// ✅ 这样写是安全的
@State tabs: string[] = ['全部', '大阿卡纳', '小阿卡纳'];

5.2 生命周期理解

ArkTS 组件有多个生命周期回调:

  • aboutToAppear(): 组件即将创建,初始化数据的好地方
  • aboutToDisappear(): 组件即将销毁,清理资源
  • onPageShow(): 页面每次显示时触发(从其他页面返回时也会触发)
typescript 复制代码
aboutToAppear(): void {
  ThemeManager.subscribe(() => {
    this.theme = ThemeManager.colors;
  });
  this.loadFavorites();
}

aboutToDisappear(): void {
  ThemeManager.unsubscribe(() => {});
}

5.3 资源引用

鸿蒙推荐使用 $r() 引用资源文件,而不是硬编码值:

typescript 复制代码
Text($r('app.string.title_home'))      // 字符串资源
  .fontSize($r('app.float.app_title_size'))  // 尺寸资源
  .fontColor($r('app.color.primary_text'))   // 颜色资源

资源文件位于 resources/base/element/ 目录下,支持按设备密度、语言等维度适配。


六、小结

本篇我们完成了:

  1. ✅ DevEco Studio 开发环境搭建与项目配置
  2. ✅ Stage 模型的项目结构设计
  3. ✅ EntryAbility 入口文件编写
  4. ✅ 首页布局和今日塔罗抽牌功能
  5. ✅ EntryCard 可复用组件提取
  6. ✅ ArkTS 严格模式语法要点

下一篇文章我们将深入 牌义列表页和路由导航,实现卡片分类筛选、详情页跳转以及列表组件的封装。


如果你正在学习鸿蒙开发,不妨跟着本系列一起动手敲代码。实践是学习鸿蒙开发最好的方式,光看不练是很难掌握 ArkTS 的各种细节的。

项目代码 : 基于 HarmonyOS API 23 + Stage 模型 + ArkTS

源码结构 : 5个页面完整塔罗牌占卜应用

下篇预告: 牌义列表 --- 分类筛选、路由传参与列表渲染优化

相关推荐
YM52e25 分钟前
买菜计算器小应用 - HarmonyOS ArkUI 开发实战-PC版本
学习·华为·harmonyos·鸿蒙·鸿蒙系统
阿捏利35 分钟前
系列总览-鸿蒙科普系列完全指南
华为·harmonyos
小雨下雨的雨1 小时前
HarmonyOS ArkUI训练营入门-组件掌握系列-Animation 动画效果实现-PC版本
学习·华为·harmonyos·鸿蒙
yuegu7771 小时前
HarmonyOS应用<节气通>开发第32篇:ArkTS语法快速入门——从TypeScript到声明式UI的完整指南
harmonyos
2601_962072552 小时前
李梦娇常识4600问|题库|打印版
sql·华为od·华为·c#·华为云·.net·harmonyos
伶俜663 小时前
鸿蒙原生应用实战(十九)ArkUI 喝水提醒 App:定时通知 + 每日记录 + 统计图表
华为·harmonyos
风华圆舞3 小时前
Flutter + 鸿蒙 Intents Kit:页面直达能力的完整接入方案
flutter·ui·华为·harmonyos
三声三视3 小时前
Electron 在鸿蒙 PC 上跑 webview,我是怎么把首屏从 4.2s 干到 1.1s 的
华为·electron·harmonyos·鸿蒙
互联网散修5 小时前
鸿蒙实战:从0到1构建功能完备的搜索页面
华为·harmonyos
花椒技术5 小时前
RN 多包热更新实践:更新校验、运行时加载与 Bridge 缓存治理
react native·react.js·harmonyos