鸿蒙原生应用开发实战(一):项目搭建与首页概览 — 电影清单App
·
鸿蒙原生应用开发实战(一):项目搭建与首页概览 — 电影清单App
前言
各位开发者朋友,本系列将带领大家从零开始,使用 HarmonyOS Stage 模型和 ArkTS 语言,开发一款完整的电影清单应用。无论你是电影爱好者还是想学习鸿蒙开发,这篇文章都能帮你快速上手。
本系列共五篇,覆盖项目搭建、添加电影、列表管理、详情评价和个人中心。
本文你将学到:
- 项目创建与 Stage 模型
- 数据模型与分类设计
- 首页仪表盘开发
- 路由注册与导航
- 示例数据与 AppStorage
一、项目创建
1.1 新建项目
打开 DevEco Studio → Create Project → Empty Ability:
- Project Name: MyApplication
- Bundle Name: com.example.myapplication
- Location: D:\harmonyos\project\6.11.12345\5\MyApplication
- Compatible SDK: API 23 (6.1.0)
1.2 Stage 模型入口
// EntryAbility.ets
import { AbilityConstant, 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 content');
return;
}
});
}
}
二、数据模型设计
2.1 核心类型
在 models/MovieData.ets 中定义数据模型:
// 电影状态
export enum MovieStatus {
WANT_TO_WATCH = 'want_to_watch', // 想看
WATCHING = 'watching', // 在看
WATCHED = 'watched' // 已看
}
// 电影数据
export interface Movie {
id: string;
title: string;
year: number;
director: string;
rating: number; // 1-5 星
status: MovieStatus;
isFavorite: boolean;
review: string;
dateAdded: string;
genreId: string;
}
// 电影分类
export interface Genre {
id: string;
name: string;
icon: string;
}
2.2 预定义分类
const ALL_GENRES: Genre[] = [
{ id: 'action', name: '动作', icon: '💥' },
{ id: 'comedy', name: '喜剧', icon: '😂' },
{ id: 'drama', name: '剧情', icon: '🎭' },
{ id: 'sci_fi', name: '科幻', icon: '🚀' },
{ id: 'horror', name: '恐怖', icon: '👻' },
{ id: 'romance', name: '爱情', icon: '❤️' },
{ id: 'animation', name: '动画', icon: '🐭' },
{ id: 'thriller', name: '悬疑', icon: '🔍' },
{ id: 'documentary', name: '纪录片', icon: '📽️' },
{ id: 'fantasy', name: '奇幻', icon: '🪄' }
];
2.3 工具函数
export function getStatusLabel(status: MovieStatus): string {
if (status === MovieStatus.WANT_TO_WATCH) return '想看';
if (status === MovieStatus.WATCHING) return '在看';
return '已看';
}
export function starsString(rating: number): string {
return '★'.repeat(rating) + '☆'.repeat(5 - rating);
}
2.4 示例数据
为了首次打开页面有内容展示,我们预置了8部经典电影:
export function getSampleMovies(): Movie[] {
return [
{ id: 'm1', title: '肖申克的救赎', year: 1994, director: '弗兰克·德拉邦特',
rating: 5, status: MovieStatus.WATCHED, isFavorite: true,
review: '经典中的经典', dateAdded: '2025-01-10', genreId: 'drama' },
{ id: 'm2', title: '星际穿越', year: 2014, director: '克里斯托弗·诺兰',
rating: 5, status: MovieStatus.WATCHED, isFavorite: true,
review: '时间、空间与爱的史诗', dateAdded: '2025-01-12', genreId: 'sci_fi' },
// ... 更多电影
];
}
三、首页仪表盘开发
3.1 页面布局
┌──────────────────────────────────┐
│ 🎬 电影清单 我的 │
├──────────────────────────────────┤
│ 🎬 总收藏 ✅ 已看 👀 想看 ⭐ 收藏│
│ 8 3 2 3 │
├──────────────────────────────────┤
│ ➕添加电影 📋全部列表 🎲随机推荐│
├──────────────────────────────────┤
│ 最近添加 全部 > │
│ ┌────────────────────────────┐ │
│ │ 🐭 疯狂动物城 ▶️ 在看 │ │
│ │ 🎭 楚门的世界 ✅ 已看 │ │
│ │ ❤️ 泰坦尼克号 👀 想看 │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
3.2 状态管理
@Entry
@Component
struct Index {
@State movies: Movie[] = [];
@State totalCount: number = 0;
@State watchedCount: number = 0;
@State wantCount: number = 0;
@State favoriteCount: number = 0;
@State recentMovies: Movie[] = [];
}
3.3 数据加载与生命周期
aboutToAppear(): void {
this.loadData();
}
onPageShow(): void {
this.loadData();
}
loadData(): void {
let stored = AppStorage.get<Movie[]>('movies');
if (stored) {
this.movies = stored;
} else {
let samples = getSampleMovies();
this.movies = samples;
AppStorage.set<Movie[]>('movies', samples);
}
this.calcStats();
}
3.4 @Builder 复用
ArkTS 中使用 @Builder 装饰器可以高效复用 UI 代码:
@Builder statCard(icon: string, label: string, value: string, color: string) {
Column() {
Text(icon).fontSize(22)
Text(value)
.fontSize(20).fontWeight(FontWeight.Bold)
.fontColor(color).margin({ top: 4 })
Text(label)
.fontSize(12).fontColor('#999999').margin({ top: 2 })
}
.layoutWeight(1)
.padding(10).backgroundColor('#FFFFFF')
.borderRadius(12).margin({ left: 3, right: 3 })
.alignItems(HorizontalAlign.Center)
}
使用方式:
Row() {
this.statCard('🎬', '总收藏', this.totalCount.toString(), '#6C63FF')
this.statCard('✅', '已看', this.watchedCount.toString(), '#2ED573')
this.statCard('👀', '想看', this.wantCount.toString(), '#FFA502')
this.statCard('⭐', '收藏', this.favoriteCount.toString(), '#FF6B6B')
}
3.5 路由跳转
// 页面跳转
router.pushUrl({ url: 'pages/AddMovie' });
router.pushUrl({ url: 'pages/DetailPage', params: { movieId: 'm1' } });
// 页面返回
router.back();
四、路由注册
4.1 main_pages.json
{
"src": [
"pages/Index",
"pages/AddMovie",
"pages/ListPage",
"pages/DetailPage",
"pages/ProfilePage"
]
}
五、ArkTS 严格模式指南
API 23 开启严格模式,以下是关键注意事项:
- @Builder 中不能有
let声明 → 所有计算需内联或通过@State提前计算 - 不能使用解构赋值 →
let [a, b] = arr不允许,换成let a = arr[0]; let b = arr[1] - 对象字面量需要显式类型 → 不能写
{ name: 'test' },要定义 interface 后赋值 .bind()不支持 → 使用闭包或 builder + onAction 替代
// ❌ 不支持的写法
@Builder card(item: Type) {
let name = item.name; // 不允许
Row() { ... }
}
// ✅ 正确的写法
@Builder card(item: Type) {
Row() {
Text(item.name) ... // 直接内联
}
}
六、运行效果
完成开发后,首页会展示:
- 4个统计卡片(总收藏/已看/想看/收藏)
- 3个快捷操作按钮(添加/列表/随机推荐)
- 最近添加的5部电影列表
- Emoji 图标 + 电影分类标签
- 状态标签以不同颜色区分(想看=橙/在看=绿/已看=紫)
总结
本文完成了:
- ✅ 项目创建与 Stage 模型理解
- ✅ 数据模型设计(Movie/Genre)
- ✅ 首页仪表盘开发(统计卡片 + 快捷操作 + 最近列表)
- ✅ 路由注册与页面导航
- ✅ @Builder 组件复用
下一篇,我们将开发添加电影页面,实现表单输入、分类选择和状态切换!
系列目录:
- ✅ 第一篇:项目搭建与首页概览(本篇)
- 📝 第二篇:添加电影与表单交互
- 📝 第三篇:电影列表与搜索筛选
- 📝 第四篇:电影详情与评分评价
- 📝 第五篇:个人中心与数据统计
更多推荐



所有评论(0)