鸿蒙原生开发实战008:基于ArkUI+ArkTS从零开发精美菜谱应用(HarmonyOS NEXT API20+ 完整版教程)
一、项目前言
随着HarmonyOS NEXT原生生态持续迭代,声明式ArkUI+ArkTS开发范式已成为鸿蒙应用开发的核心标准。对于鸿蒙初学者而言,单一组件语法学习较为零散,亟需一套功能完整、逻辑闭环、UI精美、可直接运行的综合实战项目,串联页面路由、数据处理、组件封装、交互优化等核心知识点。
本次开发的菜谱Recipe应用是移动端生活服务类经典实战项目,摒弃冗余复杂功能,聚焦核心业务逻辑,采用现代化卡片式UI设计,完美贴合鸿蒙原生开发规范。项目全程零第三方依赖,基于系统原生API开发,涵盖搜索筛选、分类切换、页面跳转、详情展示、多条件数据过滤等高频开发场景,代码结构规范、注释完整、兼容性强,非常适合用于课程设计、期末作业及入门进阶实战,轻松达到高分项目水准。
二、项目整体设计
2.1 项目开发背景
日常居家烹饪、美食学习场景中,用户需要便捷的菜谱查询工具,快速获取菜品食材、烹饪步骤、制作时长及难度等级。传统纸质菜谱查询繁琐、无法分类检索,市面多数美食APP功能臃肿、广告冗余、占用内存高。
基于HarmonyOS NEXT原生技术栈开发轻量化菜谱应用,依托ArkUI声明式UI高效渲染、ArkTS强类型语法严谨性,实现极速检索、分类浏览、详情查看核心功能,界面简洁美观、交互流畅、低功耗运行,适配鸿蒙手机、平板多端设备,完美满足轻量化美食学习需求。
2.2 核心应用场景
-
零基础学做菜:随时浏览各类菜谱,查看完整食材清单与分步烹饪教程
-
精准检索菜谱:支持菜名、食材关键词双向搜索,快速定位所需菜品
-
分类精准浏览:按家常菜、川菜、粤菜等菜系分类筛选,定向浏览
-
烹饪难度参考:直观展示菜品制作难度、耗时,适配不同烹饪水平用户
2.3 核心功能特性
-
✅ 精美卡片式菜谱列表,自适应布局、样式精致
-
✅ 多菜系分类标签筛选,一键切换分类数据源
-
✅ 实时关键词搜索,支持菜名、食材双向模糊匹配
-
✅ 完整页面路由跳转,主页与详情页参数传递
-
✅ 菜谱详情展示:食材清单、分步烹饪步骤、制作时长、难度等级
-
✅ 难度等级差异化配色展示,视觉层级清晰
-
✅ 空数据兜底渲染,无搜索结果时友好提示
-
✅ 完善的字符串、数组数据处理,代码健壮性强
2.4 项目技术栈
|
技术模块 |
技术选型与说明 |
|---|---|
|
系统版本 |
HarmonyOS NEXT(API 20及以上) |
|
开发语言 |
ArkTS(强类型TypeScript超集,鸿蒙官方标准) |
|
UI框架 |
ArkUI 声明式开发范式(数据驱动视图) |
|
核心组件 |
List、TextInput、Scroll、Column、Row、ForEach |
|
核心技术点 |
页面路由传参、多条件数据过滤、条件渲染、样式动态绑定、数组高级操作、字符串匹配 |
|
第三方依赖 |
无,纯原生API实现,零冗余依赖 |
2.5 项目页面结构
本项目采用双页面架构,结构清晰、分工明确:
-
首页(Index.ets):顶部标题栏 + 搜索框 + 分类标签栏 + 菜谱卡片列表
-
详情页(RecipeDetail.ets):返回导航栏 + 菜品信息 + 食材清单 + 分步烹饪步骤
三、核心技术知识点深度解析(高分核心考点)
本章节拆解项目核心技术原理,区别于基础教程,侧重原理讲解+踩坑优化+实战落地,是课程设计加分核心内容。
3.1 页面路由与跨页面参数传递
多页面应用的核心基础,实现主页跳转详情页、携带菜品参数,详情页解析参数渲染对应数据,同时支持返回上一页,完整覆盖鸿蒙四大核心路由方法。
核心路由API说明:
-
router.pushUrl():保留当前页,跳转至新页面(最常用) -
router.back():关闭当前页,返回上一级页面 -
router.replaceUrl():替换当前页面,无返回历史记录 -
router.getParams():接收上级页面传递的参数
完整实战代码:
// 导入路由核心模块
import router from '@ohos.router'
/**
* 跳转菜谱详情页,传递菜品ID与名称参数
* @param recipe 当前点击的菜谱对象
*/
private jumpToDetail(recipe: Recipe) {
router.pushUrl({
url: 'pages/RecipeDetail',
params: {
recipeId: recipe.id,
recipeName: recipe.name
}
})
}
// 详情页接收参数
@State currentRecipeId: number = 0
@State currentRecipeName: string = ''
aboutToAppear() {
// 安全获取路由参数,避免空指针报错
const params = router.getParams() as Record<string, Object>
if (params) {
this.currentRecipeId = params.recipeId as number
this.currentRecipeName = params.recipeName as string
}
}
// 返回上一页
private backPrevPage() {
router.back()
}
踩坑优化点:路由传参仅支持基础数据类型(数字、字符串),禁止直接传递复杂对象,避免参数丢失、解析异常。
3.2 TextInput实时搜索组件封装
基于原生TextInput实现沉浸式搜索框,搭配实时监听输入事件,实现输入即检索的交互效果,适配移动端用户操作习惯。通过圆角、内边距、背景色优化UI质感,贴合鸿蒙设计规范。
@State searchKeyword: string = ''
TextInput({
placeholder: '请输入菜谱名/食材关键词搜索',
text: this.searchKeyword
})
.width('100%')
.height(44)
.backgroundColor(Color.White)
.borderRadius(22)
.padding({ left: 16, right: 16 })
// 实时监听输入变化,动态筛选数据
.onChange((value: string) => {
this.searchKeyword = value
this.getFilteredRecipes()
})
3.3 Scroll滚动容器应用
针对食材清单、烹饪步骤等超长内容,使用Scroll实现垂直滚动,解决内容溢出屏幕问题,保证页面布局完整性,适配不同内容长度的菜品数据。
Scroll() {
Column() {
// 食材、步骤动态内容
ForEach(this.currentIngredients, (item: string) => {
Text(`• ${item}`)
.fontSize(15)
.padding({ top: 6, bottom: 6 })
})
}
.width('100%')
}
.scrollable(ScrollDirection.Vertical)
.edgeEffect(EdgeEffect.Spring) // 弹性滚动效果,提升交互质感
3.4 多条件复合数据过滤(核心业务)
整合分类筛选+关键词模糊搜索双条件过滤,同时支持菜名、食材双向匹配,采用小写统一匹配规则,实现不区分大小写搜索,适配用户多样化检索需求,代码逻辑分层清晰、可拓展性极强。
// 选中的分类标签
@State selectedCategory: string = '全部'
/**
* 多条件过滤菜谱数据
* @returns 筛选后的菜谱数组
*/
private getFilteredRecipes(): Recipe[] {
// 初始化完整数据源
let resultList = this.recipes
// 条件1:按菜系分类筛选
if (this.selectedCategory !== '全部') {
resultList = resultList.filter(item => item.category === this.selectedCategory)
}
// 条件2:关键词模糊搜索
const keyword = this.searchKeyword.trim().toLowerCase()
if (keyword) {
resultList = resultList.filter(item => {
// 匹配菜名 || 匹配任意食材
return item.name.toLowerCase().includes(keyword)
|| item.ingredients.some(ing => ing.toLowerCase().includes(keyword))
})
}
return resultList
}
3.5 动态样式与多条件判断
根据菜品难度等级动态渲染文字颜色,通过分支判断区分简单、中等、困难三个等级,视觉层级清晰,提升页面精致度,是动态UI开发的典型应用。
/**
* 根据难度返回对应主题色
* @param difficulty 菜品难度等级
* @returns 十六进制颜色码
*/
private getDifficultyColor(difficulty: string): string {
switch (difficulty) {
case '简单':
return '#10b981' // 绿色-低难度
case '中等':
return '#f59e0b' // 黄色-中等难度
case '困难':
return '#ef4444' // 红色-高难度
default:
return '#666666'
}
}
3.6 条件渲染三种高阶写法
项目综合运用鸿蒙三种主流条件渲染方式,适配不同业务场景,代码简洁高效:
// 1. if/else 分支渲染(适配大块布局切换)
if (this.getFilteredRecipes().length === 0) {
Text('暂无匹配菜谱,请更换关键词或分类')
.fontSize(16)
.fontColor('#999')
} else {
// 菜谱列表布局
}
// 2. 三元运算符(适配单行文本、简单状态切换)
Text(this.isLoading ? '加载中...' : '共${this.getFilteredRecipes().length}道菜谱')
// 3. 短路运算(适配局部组件显隐)
{this.searchKeyword && Text('正在搜索:${this.searchKeyword}')}
3.7 现代化卡片式布局实现
采用上下分层卡片设计,结合圆角、阴影、内边距、外边距优化UI,符合鸿蒙极简设计风格,布局规整、适配性强,可直接复用至各类列表项目。
Column() {
// 卡片顶部:菜品展示区
Column() {
Text(recipe.name)
.fontSize(20)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height(140)
.backgroundColor('#f97316')
.justifyContent(FlexAlign.Center)
.borderRadius({ topLeft: 12, topRight: 12 })
// 卡片底部:菜品信息区
Column() {
Row() {
Text(recipe.category)
.fontSize(12)
.backgroundColor('#f1f5f9')
.borderRadius(4)
.padding({ left: 8, right: 8 })
Text(recipe.difficulty)
.fontSize(12)
.fontColor(this.getDifficultyColor(recipe.difficulty))
.margin({ left: 10 })
}
Text(`制作时长:${recipe.cookTime}分钟`)
.fontSize(14)
.fontColor('#666')
.margin({ top: 8 })
}
.padding(12)
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 6, color: '#1a000000', offsetX: 2, offsetY: 2 })
四、完整数据结构与业务逻辑实现
4.1 定义菜谱实体类
标准化菜品数据结构,统一字段规范,便于全局数据管理与渲染,提升代码可维护性。
class Recipe {
id: number; // 菜品唯一ID
name: string; // 菜品名称
category: string; // 所属菜系分类
ingredients: string[]; // 食材清单数组
steps: string[]; // 烹饪步骤数组
cookTime: number; // 制作时长(分钟)
difficulty: string; // 难度等级:简单/中等/困难
image: string; // 菜品配图标识
constructor(id: number, name: string, category: string, ingredients: string[], steps: string[], cookTime: number, difficulty: string, image: string) {
this.id = id;
this.name = name;
this.category = category;
this.ingredients = ingredients;
this.steps = steps;
this.cookTime = cookTime;
this.difficulty = difficulty;
this.image = image;
}
}
4.2 初始化模拟菜谱数据
页面加载完成后自动初始化多菜系、多难度菜谱数据,覆盖项目所有筛选、搜索场景。
@State recipes: Recipe[] = []
aboutToAppear() {
// 初始化模拟菜谱数据
this.recipes = [
new Recipe(
1,
'红烧肉',
'家常菜',
['五花肉500g', '生姜3片', '葱2根', '八角2个', '冰糖适量', '生抽2勺', '老抽1勺', '料酒1勺'],
['五花肉切块,冷水下锅焯水去除血沫', '锅中少油,加入冰糖炒出焦糖色', '放入五花肉快速翻炒上色', '加入葱姜八角和适量热水', '大火烧开转小火慢炖60分钟', '大火收汁,翻炒均匀即可出锅'],
90,
'中等',
'hongshaorou'
),
new Recipe(
2,
'宫保鸡丁',
'川菜',
['鸡胸肉300g', '花生米50g', '干辣椒5个', '花椒10粒', '葱姜蒜适量', '黄瓜半根'],
['鸡胸肉切丁,加盐、料酒腌制15分钟', '冷油下锅炸熟花生米备用', '锅中爆香花椒、干辣椒、葱姜蒜', '下入鸡丁翻炒至变色', '加入黄瓜丁、调料翻炒入味', '最后加入花生米翻炒均匀出锅'],
30,
'简单',
'gongbaojiding'
),
new Recipe(
3,
'白切鸡',
'粤菜',
['三黄鸡1只', '生姜5片', '葱3根', '料酒2勺', '沙姜适量', '生抽少许'],
['鸡肉处理干净,冷水浸泡去血水', '锅中烧水,加入葱姜料酒', '水微沸后放入鸡肉浸煮20分钟', '关火焖10分钟充分入味', '捞出过冰水,肉质更紧实', '切块搭配沙姜酱汁即可食用'],
40,
'简单',
'baiqieji'
)
]
}
五、项目常见Bug与精细化优化方案(高分优化点)
问题1:搜索结果匹配不准确、大小写敏感
问题现象:输入大写关键词无法匹配小写菜品名称,搜索容错性差。
优化方案:统一将关键词、菜品名称、食材名称转为小写,实现不区分大小写模糊匹配,大幅提升搜索容错性。
问题2:路由跳转参数丢失、解析报错
问题现象:跳转详情页后无法获取数据,页面空白、程序闪退。
优化方案:仅传递数字、字符串等基础类型参数,接收参数时增加空值判断,避免空指针异常。
问题3:分类切换后列表不刷新
问题现象:点击分类标签,菜谱列表无变化,数据不更新。
优化方案:ForEach强制绑定过滤后的动态数据源 getFilteredRecipes(),而非固定原始数组,确保每次筛选、搜索都能实时刷新UI。
问题4:空数据页面体验差
优化方案:增加空数据兜底文案,友好提示用户更换搜索词或分类,避免空白页面影响交互体验。
本菜谱应用是一套零基础友好、知识点全面、业务逻辑完整的HarmonyOS NEXT原生实战项目,全程遵循鸿蒙最新开发规范,基于ArkTS+ArkUI纯原生开发,无任何第三方冗余依赖。
通过本项目实战,可熟练掌握页面路由跳转与参数传递、实时搜索、多条件数据筛选、动态样式渲染、卡片式UI布局、数组与字符串高级处理、条件渲染等鸿蒙核心开发技能,完整理解移动端轻量化生活服务类应用的开发流程与优化思路。
更多推荐






所有评论(0)