鸿蒙5.0开发入门:从ArkTS到ArkUI的完整实战指南
2026/9/7 6:47:37 网站建设 项目流程

简介:面向鸿蒙5.0(HarmonyOS NEXT)初学者的App开发入门Demo,将工程模板、构建配置与示例代码整合为可直接走通的实操包,适合零基础或刚接触ArkTS/ets的开发者快速建立鸿蒙应用整体认知。压缩包共445个文件,体积约1.84MB,以js、json、ts、ets源码为主,另含build-profile.json5、oh-package.json5等构建与包管理配置,以及clang-format、gitignore等工程规范文件,结构上覆盖从项目初始化到编译部署的完整链路。目前已有453人学习下载。通过对照AppScope目录、hvigor脚本和各模块配置,读者可理解鸿蒙项目的分层组织方式,掌握依赖锁定、代码检查与本地环境配置等关键环节,并基于自带HAP和示例页面动手修改,缩短从阅读文档到独立开发之间的距离。

1. 为什么说鸿蒙5.0是App开发的一个分水岭

做过几年移动端开发的朋友应该能明显感觉到,鸿蒙5.0(HarmonyOS 5.0)和之前的版本有本质区别。往大了说,它彻底放弃了兼容Android APK的路线,从系统底层到应用框架全部走自研路线,这意味着App开发逻辑跟传统的Android开发完全分道扬镳。往实际了说,以前你写Android项目还能顺手打一个鸿蒙包,现在这条路基本堵死了,想在这个生态里做应用,就必须重新学一套开发范式,也就是DevEco Studio配合ArkTS语言、ArkUI声明式框架这一整套东西。

这篇文章我准备以一个完整可运行的入门Demo为主线,把鸿蒙5.0的工程结构、页面开发、状态管理、打包调试等核心环节都过一遍。这个Demo不需要多花哨,但一定要跑得起来、看得懂、改得动,适合刚接触鸿蒙生态的前端开发者、Android开发者,以及想评估鸿蒙开发成本的技术负责人参考。我不会只贴代码,还会把每一步背后的设计逻辑和坑点讲清楚。

先说一个最直观的感受:如果你有TypeScript或SwiftUI的基础,学鸿蒙开发的曲线会平缓很多。ArkTS基于TypeScript做了静态类型强约束,而ArkUI的布局写法跟声明式UI的思路几乎一脉相承。如果你只有传统Android XML或View系统的经验,那需要先适应组件化、状态驱动的思维模式。别急,下面从零开始带你把这套东西撸一遍。

2. 开发环境搭建与工程结构解读

2.1 DevEco Studio的下载与版本选择

开发鸿蒙App的官方IDE是DevEco Studio,本质上是基于IntelliJ IDEA定制的。下载地址在华为开发者官网,这个没什么好绕弯的。有一点要注意,鸿蒙5.0对应的是DevEco Studio 5.0以上版本,SDK方面建议直接安装API 12或更高版本,因为5.0系统全面转向了鸿蒙内核,API级别太低会直接影响真机调试和部分系统能力调用。

安装过程没什么特别,Windows和macOS都有对应安装包,按默认选项安装即可。安装完成后首次启动会让你配置SDK路径,建议用默认路径省心。这里有个容易忽略的点:DevEco Studio的SDK Manager里会分“Public SDK”和“Full SDK”,一般开发用Public就够,但如果你要调试系统接口、申请某些敏感权限,就需要切换到Full SDK并签署相应协议。入门阶段不用碰Full SDK,免得给自己挖坑。

提示:开发工具版本跟手机系统版本不匹配是常见问题,后面专门用一节讲怎么排查。

2.2 创建第一个工程:模板选择与初始化

打开DevEco Studio,选择“Create Project”,会出现多个模板。我们选“Empty Ability”就行,这个模板生成最干净的Hello World工程,方便看透目录结构。如果你选带TabBar的模板,初始代码会多一些,反而不利于理解底层脉络。

工程创建过程中需要填Project Name(如HarmonyDemo)、Bundle name(如com.example.harmonydemo),这个Bundle name相当于应用的唯一标识,类似Android的applicationId,创建后不好改,想清楚再填。Project type选“Application”,其他选项默认,点击Finish后IDE就开始自动同步工程,第一次会比较慢,因为要下载依赖组件,吃个饭再回来看都正常。

等待同步完成后,你会看到这样的核心目录结构:

HarmonyDemo/ ├── AppScope/ │ ├── app.json5 # 应用全局配置 │ └── resources/ # 应用级资源 ├── entry/ # 应用的主模块 │ ├── src/ │ │ ├── main/ │ │ │ ├── ets/ # 源码目录 │ │ │ │ ├── entryability/ # Ability生命周期逻辑 │ │ │ │ └── pages/ # 页面文件 │ │ │ ├── resources/ # 模块资源 │ │ │ └── module.json5 # 模块配置 │ ├── build-profile.json5 # 构建配置 │ └── hvigorfile.ts # 构建脚本入口 ├── oh-package.json5 # 依赖声明 └── build-profile.json5 # 全局构建配置

简单来说,entry代表应用的主模块,Android里你可能叫app模块,性质一样。module.json5里声明了Ability、权限、设备类型等关键信息,相当于AndroidManifest.xml和build.gradle的部分合体。

2.3 工程关键配置:module.json5与app.json5

module.json5是每个模块的核心配置,入门需要关注这几个字段:

{ "module": { "name": "entry", "type": "entry", // 模块类型,entry代表应用入口模块 "description": "$string:module_desc", "mainElement": "EntryAbility", // 入口Ability "deviceTypes": ["phone", "tablet"], "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ts", "description": "$string:EntryAbility_desc", "icon": "$media:icon", "label": "$string:EntryAbility_label", "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ { "entities": ["entity.system.home"], "actions": ["action.system.home"] } ] } ] } }

不用强记,但理解两个点:第一,srcEntry指向Ability入口文件,这是应用启动时加载的第一个代码文件;第二,skills里的action.system.home是应用图标的入口配置,类似于Android的ACTION_MAIN和CATEGORY_LAUNCHER组合。改错这里会导致应用不出现在桌面上,排查时记得看一眼。

app.json5则管应用级信息,比如应用名称、版本号(versionCodeversionName)、SDK兼容版本等。版本号这里容易踩坑,因为鸿蒙有compatibleSdkVersiontargetSdkVersion两个概念,前者决定最低可运行版本,后者决定目标版本,配置不当会直接编译失败。

3. ArkTS与ArkUI:鸿蒙开发的核心语言与框架

3.1 ArkTS为什么强调“静态类型”

ArkTS不是一门全新的语言,它是TypeScript的超集,在TS基础上强化了静态类型检查和运行时约束。为什么华为要这么干?一个重要的原因是移动端性能。TypeScript本身是弱约束的解释型语言,面向UI这种高频交互场景,如果类型全靠运行时推断,性能和稳定性都会打折扣。ArkTS相当于在编译阶段就把绝大多数类型问题拦在门外,减少运行时错误。

对开发者来说,这意味着写代码时更“束手束脚”,不能随意any一把梭,不能像JS那样灵活地动态增删对象属性。一开始会觉得不习惯,比如这种情况在JS里没问题,但ArkTS会直接报错:

// 错误示例:ArkTS不允许动态添加属性 let person = { name: 'Tom' }; person.age = 18; // 编译报错

正确做法是定义interface明确结构:

interface Person { name: string; age?: number; // 可选属性 } let person: Person = { name: 'Tom' }; person.age = 18;

一句话总结:把TypeScript里那些“比较容易钻空子”的写法堵死,用更严格的规范换性能和稳定。写惯强类型语言的人适应起来很快,写惯JS的人前期会多踩几个编译报错,习惯了也就好了。

3.2 ArkUI声明式UI的核心概念

ArkUI是整个鸿蒙UI框架的名字,核心思想是“描述UI状态,而非手动操作UI”。你只需要声明组件树和它们的数据依赖关系,数据变化时框架自动刷新界面。听上去是不是很像SwiftUI或者Flutter?没错,就是这个路子。

一个最简页面长这样:

@Entry @Component struct Index { @State message: string = 'Hello HarmonyOS'; build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) Button('点击更新') .onClick(() => { this.message = 'Hello ArkTS!'; }) } .width('100%') } .height('100%') } }

几个关键装饰器要搞清楚:

  • @Entry:标记当前组件为页面入口,一个页面文件只有能有一个。
  • @Component:标记这是一个自定义组件,可以组合其他组件。
  • @State:标记这是一个状态变量,当它的值变化时,界面会自动刷新。
  • struct:定义组件结构体的关键字,类似class但功能上有差异。

这个“声明式”的思维转变很重要。以前写Android是findViewById拿到控件,再setText更新内容,也就是命令式操作。现在你只需要把数据和UI绑定起来,状态的变更由框架接管。刚开始不适应,但写过两个页面之后就会觉得这种方式写UI效率高很多,尤其是列表、表单这类频繁变更的场景。

3.3 基础组件与布局方式速览

ArkUI的布局核心是“容器组件+子组件”的嵌套关系,类似Android的ViewGroup。入门阶段最常用的几个:

  • Row:水平排列子组件
  • Column:垂直排列子组件
  • Stack:层叠排列,子组件可以重叠
  • List+ListItem:高效长列表
  • Grid:网格布局,类似Android的RecyclerView GridLayoutManager

基础控件方面则包括Text(文本)、Button(按钮)、Image(图片)、TextInput(输入框)、Toggle(开关)等,命名和React Native、Flutter里的大同小异。布局属性上,有几个高频用法要记住:

// 通用布局属性 .width('100%') // 宽度 .height(200) // 高度,数字默认vp单位 .backgroundColor('#f0f0f0') .padding(16) // 内边距 .margin({ top: 8, bottom: 8 }) // 外边距 .borderRadius(8) // 圆角 .alignItems(HorizontalAlign.Center) // 子组件对齐方式 .justifyContent(FlexAlign.SpaceBetween) // 主轴上分布方式

这里有一个单位的概念:默认数字单位是vp(virtual pixel),类似Android的dp,适配不同屏幕密度的相对单位。字体大小同理,用fp(font pixel),会自动跟随系统字体缩放设置。这个细节不搞清楚,后续适配会吃亏。

4. 实操:从零编写一个可运行的鸿蒙入门Demo

4.1 Demo的需求定位与页面规划

既然叫入门Demo,就别贪多,我把它设计成一个“待办事项”应用。为什么选这个?因为它涵盖了开发中最常用的几个能力:列表展示、输入交互、状态管理、页面跳转、动态增删数据。把这些跑通,你基本就掌握了一个鸿蒙App开发的完整闭环。

功能拆成两个页面:

  • 首页(Index):展示待办列表,底部有一个输入框和添加按钮,可以动态添加待办事项,点击事项可以删除。
  • 详情页(Detail):展示从首页传递过来的具体事项内容,模拟一个典型的参数传递场景。

这个规模对于第一次接触鸿蒙开发的人来说刚刚好,不会因为功能太多而迷失在代码里,又能完整体验一个App从数据到界面的完整链路。

4.2 数据模型与全局状态设计

在ArkTS中,数据模型推荐用class或interface描述,配合@State@Observed等装饰器实现响应式。我们的待办事项数据做一个简单的class:

// model/TodoItem.ets @Observed export class TodoItem { id: number; title: string; isDone: boolean = false; constructor(id: number, title: string) { this.id = id; this.title = title; } }

@Observed装饰器的含义是“这个类的属性变化会被观察”,配合@ObjectLink可以在父子组件之间建立细粒度的数据关联。但这里有一个新手容易搞混的点:@State@Observed的区别。简单来说,@State是用在组件里修饰普通类型变量的(string、number、boolean、普通数组等),@Observed是修饰class本身的,让其实例可以被观察。如果class没有加@Observed,即使组件里用@State接收了它的实例,修改内部属性也不会触发UI刷新。

不过在我们的Demo中,为了避免一开始就引入太复杂的装饰器组合,可以在页面内部直接用@State管理一个数组。真正的项目里再逐步引入@Observed@ObjectLink来拆分组件,入门阶段先保证跑通。

4.3 首页开发:列表展示与输入交互

页面默认生成在entry/src/main/ets/pages/Index.ets,我们直接改造它。完整代码如下:

import { TodoItem } from '../model/TodoItem'; @Entry @Component struct Index { @State todoList: TodoItem[] = [ new TodoItem(1, '学习鸿蒙ArkTS语法'), new TodoItem(2, '搭建开发环境'), new TodoItem(3, '跑通第一个Demo') ]; @State inputValue: string = ''; private nextId: number = 4; build() { Column() { // 标题栏 Text('我的待办') .fontSize(24) .fontWeight(FontWeight.Bold) .width('100%') .padding(16) .backgroundColor('#F1F3F5') // 待办列表 List({ space: 12 }) { ForEach(this.todoList, (item: TodoItem) => { ListItem() { Row() { Text(item.title) .fontSize(16) .decoration({ type: item.isDone ? TextDecorationType.LineThrough : TextDecorationType.None, color: '#999999' }) .layoutWeight(1) Button(item.isDone ? '已完成' : '标记完成') .fontSize(12) .height(32) .type(item.isDone ? ButtonType.Normal : ButtonType.Capsule) .onClick(() => { item.isDone = !item.isDone; }) } .padding(12) .backgroundColor('#FFFFFF') .borderRadius(8) .shadow({ radius: 4, color: '#11000000', offsetY: 2 }) } .onClick(() => { this.deleteTodo(item.id); }) }, (item: TodoItem) => item.id.toString()) } .layoutWeight(1) .width('100%') .padding({ left: 16, right: 16, top: 8 }) // 底部输入区 Row() { TextInput({ placeholder: '输入新的待办...', text: this.inputValue }) .layoutWeight(1) .height(44) .backgroundColor('#F1F3F5') .borderRadius(22) .padding({ left: 16, right: 16 }) .onChange((value: string) => { this.inputValue = value; }) Button('添加') .height(44) .margin({ left: 8 }) .onClick(() => { this.addTodo(); }) } .width('100%') .padding(12) .backgroundColor('#FFFFFF') } .width('100%') .height('100%') .backgroundColor('#F7F8FA') } addTodo() { const title = this.inputValue.trim(); if (title === '') { return; } this.todoList.push(new TodoItem(this.nextId, title)); this.nextId++; this.inputValue = ''; } deleteTodo(id: number) { this.todoList = this.todoList.filter((item: TodoItem) => item.id !== id); } }

这段代码里有几个值得注意的点。

ForEach的第一个参数是数据源数组,第二个是生成每一项子组件的函数,第三个是key生成函数。key一定要稳定唯一,这里用item.id.toString(),注意第二参数类型是(item: TodoItem, index?: number) => void,不是简单的回调。如果没有第三个参数,框架会默认用index作为key,这样列表删除或排序时可能出现UI复用错乱。

列表项的删除我直接绑定了ListItemonClick,但这个设计有一点不合理:因为“标记完成”按钮也在这个列表项里,点击按钮时事件会冒泡,导致按钮操作完紧接着触发了删除。所以实际运行时你会发现,一个按钮点击同时触发了两个动作。修正方法是给按钮的点击事件加stopPropagation(),代码里调整一下:

Button(...) .onClick((event: ClickEvent) => { event.stopPropagation(); item.isDone = !item.isDone; })

这种事件冒泡问题在新手阶段非常隐蔽,因为编译不报错,逻辑也能跑,但行为完全不对。这也是我强烈建议做Demo时边运行边调试,别一口气写完再统一断言的另一个原因。

4.4 详情页开发:页面跳转与参数传递

再来一个详情页,接收从首页传过来的标题文本。新建文件entry/src/main/ets/pages/Detail.ets

@Entry @Component struct Detail { @State title: string = ''; aboutToAppear(): void { // 从路由参数中获取title const params = router.getParams() as Record<string, string>; if (params && params.title) { this.title = params.title; } } build() { Column() { Text('详情页') .fontSize(24) .fontWeight(FontWeight.Bold) .width('100%') .padding(16) .backgroundColor('#F1F3F5') Text(this.title) .fontSize(20) .margin({ top: 40, left: 20, right: 20 }) .width('100%') Blank() Button('返回') .width('80%') .onClick(() => { router.back(); }) .margin({ bottom: 40 }) } .width('100%') .height('100%') .backgroundColor('#F7F8FA') } }

对应的,首页里如果要跳转到这个详情页,需要引入路由API并把title传过去:

import { router } from '@kit.ArkUI'; // 在某个按钮的点击事件里 router.pushUrl({ url: 'pages/Detail', params: { title: item.title } });

这里有个细节:router.pushUrlurl路径是pages/Detail,不需要后缀.ets,这个路径是相对于entry/src/main/ets目录的。如果页面文件放在子目录下,路径要对应写全,比如pages/second/Detail。另外,鸿蒙的routerNavigation是两套路由体系,router偏传统、简单直接;Navigation更现代,支持嵌套容器、自定义转场动画、跨包路由等,官方也在逐步推荐用Navigation。新手入门用router最容易理解,项目大了再考虑迁移Navigation不迟。

4.5 关于命名与代码组织的几点建议

入门Demo的代码量不大,全部塞到pages下也勉强可以,但一旦页面多了,这堆文件就会变成灾难。建议从Day 1就按职责分目录:

entry/src/main/ets/ ├── entryability/ # Ability相关 ├── pages/ # 路由页面 ├── model/ # 数据模型 ├── viewmodel/ # 状态管理逻辑(可选) ├── components/ # 可复用的自定义组件 └── common/ # 常量、工具函数

这不是强制要求,但文件归类越清晰,后面找东西越省心。很多人把项目写烂不是因为一开始逻辑多复杂,而是因为目录太乱,改一个需求要翻半天文件。

5. 构建产物:HAP、HSP、HAR到底是什么

5.1 三类包体的定位与区别

鸿蒙生态的包类型比Android多一点,新手首先要分清HAP、HSP、HAR三个概念。可以类比着记忆:

  • HAP(HarmonyOS Ability Package):应用安装包,相当于Android里的APK。它包含一个模块的代码、资源和配置文件,是最终安装到设备上的基本单元。
  • HAR(HarmonyOS Archive):静态共享包,类似Android的AAR或Java的JAR。代码和资源被编译进宿主HAP,不能独立运行,也没自己的Ability。
  • HSP(HarmonyOS Shared Package):动态共享包,类似Android的动态模块或插件化方案。运行时按需加载,多个HAP可以共享同一份HSP,用来做模块化、动态下发都很方便。

用一张表快速对比:

类型能否安装运行复用范围典型使用场景
HAP单模块App入口模块、功能模块
HAR不能编译期静态复用工具库、UI组件库、基础能力封装
HSP不能独立安装运行期按需加载动态功能模块、多渠道共享业务代码

对一个入门Demo来说,你最终打出来的就是HAP包。默认模板还会在oh-package.json5里带一些HAR依赖,比如路由、工具库,本质就是引入静态共享包来复用别人的能力。

5.2 如何打出一个可安装的HAP包

在DevEco Studio里,打包入口在菜单栏“Build”,有两个选项需要搞清楚:

  • Build Hap(s)/APP(s) -> Build Hap(s):只构建HAP包,用于真机调试或本地自测。
  • Build Hap(s)/APP(s) -> Build APP(s):构建一个.APP文件,这是应用市场的上架格式,里面可以包含多个HAP/HSP。

调试阶段我们主要用“Build Hap(s)”。默认的输出目录在模块下的build/outputs/default/,你会看到类似entry-default-signed.hap的文件。带signed说明签名过,可以直接往手机上装;不带的说明没签名,装不上。

提示:如果你看不到输出包或编译报错签名问题,优先检查Build菜单里的“Signing Configs”,确认是否配置了自动签名。登录华为账号后,DevEco通常会自动生成一个调试证书,省去手动配置Profile的麻烦。

5.3 关于“可以打包成hap、hsp、har的鸿蒙demo”

你可能会搜到一些项目说“支持打出hap、hsp、har三种包”,这种demo一般是把一个简单库函数分别以静态共享包(HAR)和动态共享包(HSP)形式提供,再用主模块(HAP)依赖它们,最后展示三种产物的打包方法。对于入门理解模块化工程很有价值,但不要在第一个练手项目里就强行上这种多模块结构。先把单模块的HAP跑明白,再拆HAR、HSP,路线更稳妥。

6. 真机调试与签名配置专项

6.1 真机调试的前置条件

鸿蒙的模拟器跑起来比较慢,而且有些传感器能力模拟不了,所以强烈建议用真机调试。前置条件有四个:

  • 手机开启“开发者模式”,在“设置-关于本机”里连续点击“版本号”7次。
  • 在“系统和更新-开发人员选项”里打开“USB调试”。
  • 用USB数据线连接电脑,手机上弹出授权窗口时允许调试。
  • DevEco Studio的“File -> Project Structure -> Signing Configs”里勾选“Automatically generate signature”,并登录华为账号。

前三个条件和Android调试基本一致,第四个是鸿蒙特有的签名要求。鸿蒙系统对应用签名校验很严格,没有签名或签名不匹配,应用根本装不上去。

6.2 开发时cli与手机端版本不同怎么解决

这是很多新手在真机调试时被卡住最多的地方。具体表现是:DevEco Studio的hdc工具能识别到设备,但安装时或者运行时提示版本不匹配、SDK不兼容、连接失败等。

常见的坑有这几种:

第一,DevEco Studio版本太老,识别不了新手机。手机系统升级到鸿蒙5.0之后,旧版DevEco带的SDK和hdc跟不上新系统的通讯协议,表现为设备连接不上或设备列表为空。解决办法是升级DevEco Studio到5.0及以上版本,升级SDK到API 12及以上。

第二,手机系统和工程配置的targetSdkVersion不一致。工程的compileSdkVersion最好不低于真机系统对应的API版本。你可以在项目build-profile.json5里查看当前的compileSdkVersion,在真机的“设置-关于本机”里确认系统版本对应的API等级,两者偏差过大就会出现兼容性问题。

第三,hdc版本不一致。命令行工具的hdc版本跟IDE内置的版本不一致时,会出现连接成功后无法安装、无法启动调试进程的问题。在DevEco的Terminal里执行:

hdc version

看一下输出,然后和SDK目录下hdc的版本对比。如果不一致,把命令行使用的hdc路径切换到DevEco安装目录下的SDK工具路径,或者直接卸载重装命令行工具。

第四,签名证书和设备的API级别不匹配。自动签名生成的Profile如果只在某个API级别下有效,手机系统升级后可能失效。这种情况在“Signing Configs”里重新生成一次签名即可。

总的来说,核心思路就一句:保证IDE、SDK、手机系统三者版本对齐。版本越新越不容易出兼容问题,不要为了省事拖着老版本不升级。

6.3 模拟器调试的注意事项

如果你的真机不方便连,也可以用模拟器。DevEco Studio的Device Manager里可以下载Phone模拟器镜像。需要注意两点:模拟器对电脑配置要求不低,至少16GB内存才比较流畅;模拟器运行的是x86镜像,少数真机上正常的功能在模拟器上可能有细微差异,比如某些传感器、定位能力。所以模拟器适合快速验证UI和逻辑,最终上线前还是得真机过一遍。

7. 常见编译与运行问题排查速查

写鸿蒙Demo的初期,我几乎每个环节都踩过坑,有些问题搜遍全网也找不到满意答案,只能自己翻日志和源码。这里把常见问题整理出一份速查表,帮大家少走弯路。

问题现象可能原因排查思路与解决
工程同步失败,ohpm下载超时网络原因或镜像源不稳定oh-package.json5里检查依赖;换用国内镜像源;若依赖来自华为仓库还是超时,关闭代理或换网络
编译报错“undefined symbol”页面或组件引用了不存在的变量/方法检查import路径是否写全,是否忘了引入@kit.ArkUI等基础依赖
预览器白屏组件树渲染异常打开Previewer的日志面板,重点看是否有@Entry重复、require循环等提示;确认页面所在路径和编译产物一致
模拟器卡顿电脑内存不足或镜像版本问题关闭其他大型应用,清理模拟器缓存;更建议直接切真机调试
真机显示“安装失败”签名错误或包不一致确认“Automatically generate signature”已勾选;删除手机上之前的旧应用再安装;检查设备API等级
List无法滚动布局容器给了固定高度但没有指定可滚动方向List需要约束高度,同时在Column里使用layoutWeight(1)占满剩余空间
状态更新不刷新@State修饰的对象内部属性变更如果是class实例,需要给class加@Observed,组件里用@ObjectLink接收;或者直接替换整个对象引用
TextInput输入卡顿绑定了重量级状态输入事件不要触发大数组的重排,尽量拆分组件,让TextInput自身状态独立
字体显示异常/布局挤变单位混用或未适配间距、尺寸统一用vp,字体用fp;不要直接套用Android dp/px的数值

这几个问题里,状态不刷新是最影响开发效率的,因为逻辑上觉得没问题,但界面就是不动。核心解决思路就两条:要么把需要观察的类用@Observed装饰,要么每次修改数据时重新赋一个新数组引用。比如删除待办时写this.todoList = this.todoList.filter(...),而不是this.todoList.splice(...),这样才能让框架检测到数组引用变化。

8. 运行第一个Demo时的心得与扩展建议

到这里,你手里的Demo已经具备了一个App的完整雏形:有页面、有数据、有跳转、有交互、能打包、能调试。把这套流程完整走一遍,鸿蒙开发的基本功就算是有了三分之一。剩下的大头是深入学习ArkUI的高级组件和动画系统、熟练掌握状态管理框架(比如V1/V2两种状态管理模型的选择)、理解Ability框架的启动模式和任务栈逻辑。

分享一个我实际体会比较深的点:鸿蒙的几个装饰器机制,尤其是@State@Prop@Link@Provide@Consume这一套,是理解整个响应式UI的关键。入门的时候往往只用到@State,但一旦页面结构复杂、组件需要共享状态时,光靠@State就会把代码写得很痛苦。建议下一步就系统过一遍状态管理相关的官方文档,配合官方的“状态管理”Demo逐个测试,这个投入的回报率非常高。

最后分享两个小技巧。第一,在DevEco Studio里多用Previewer,它能边改代码边看效果,比反复上真机快很多;但遇到路由跳转、系统能力调用时Previewer支持有限,还是要走真机。第二,多看系统自带的示例工程,DevEco Studio新建工程时自带的模板代码就是最正宗的最佳实践,很多组件的用法直接参考模板比自己瞎试省力不少。

鸿蒙5.0这个生态才刚进入快速发展期,对开发者来说既是新挑战也是新机会。趁早把这套工具链和语言栈摸熟,无论从技术积累还是职业发展的角度,都是一件值得做的事。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询