鸿蒙原生应用实战(一):塔罗牌占卜App开发 --- 环境搭建与首页开发
前言
随着华为鸿蒙生态的快速发展,越来越多的开发者开始投身鸿蒙原生应用开发。本系列文章将以一个完整的 塔罗牌占卜 App 为案例,从零开始讲解鸿蒙原生应用的完整开发流程。无论你是刚接触鸿蒙开发的新手,还是有一定经验的开发者,都能从中获得实践参考。
本文是第一篇,聚焦于 开发环境搭建、项目初始化、Stage 模型理解以及首页页面的实现。我们将深入探讨鸿蒙开发中的常见问题、最佳实践和性能优化技巧,帮助你在实际项目中少走弯路。
为什么选择塔罗牌 App 作为案例?
- 功能全面:包含UI布局、状态管理、路由跳转、主题切换等核心功能
- 数据驱动:涉及本地数据存储、随机算法、卡片展示等数据处理逻辑
- 组件化:适合展示ArkTS的组件化开发模式
- 实用性强:可以扩展为完整的商业化应用
- 学习曲线平缓:从简单到复杂,逐步掌握鸿蒙开发技能
本文目标读者:
- 有一定前端开发经验,想学习鸿蒙原生应用开发
- 已经了解 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 首页需要包含:
- 顶部品牌区:Logo、标题、主题切换按钮
- 今日塔罗:随机抽牌展示,点击可再抽
- 功能导航:三个入口卡片(全部牌义、牌阵解读、我的收藏)
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/ 目录下,支持按设备密度、语言等维度适配。

六、小结
本篇我们完成了:
- ✅ DevEco Studio 开发环境搭建与项目配置
- ✅ Stage 模型的项目结构设计
- ✅ EntryAbility 入口文件编写
- ✅ 首页布局和今日塔罗抽牌功能
- ✅ EntryCard 可复用组件提取
- ✅ ArkTS 严格模式语法要点
下一篇文章我们将深入 牌义列表页和路由导航,实现卡片分类筛选、详情页跳转以及列表组件的封装。
如果你正在学习鸿蒙开发,不妨跟着本系列一起动手敲代码。实践是学习鸿蒙开发最好的方式,光看不练是很难掌握 ArkTS 的各种细节的。
项目代码 : 基于 HarmonyOS API 23 + Stage 模型 + ArkTS
源码结构 : 5个页面完整塔罗牌占卜应用
下篇预告: 牌义列表 --- 分类筛选、路由传参与列表渲染优化