本文是“鸿蒙初开:从零构建应用世界”系列的第一篇。本系列旨在帮助开发者系统掌握HarmonyOS应用开发技能,最终通过HarmonyOS应用开发者高级认证。高级认证考试包含理论考试和编程考试两个环节,各1小时,均需达到80分才能通过认证。

理论考试侧重考察ArkTS高级语法、鸿蒙应用架构、分布式能力、性能优化等核心知识点,编程考试则要求使用DevEco Studio完成指定项目的开发。因此,从第一课开始,我们就需要建立“理论学习”与“动手实操”并重的学习思维。

这一部分的目标,是帮你从“我想学”过渡到“我能动手”。我们将通过理解工程项目结构、认识ArkTS声明式UI的基本语法,以及亲手写下并跑通第一段代码,建立起对鸿蒙应用开发最直观的体感。这堂课不会让你成为语法大师,但会让你成为一个“知道怎么开始”的人。

理解你的战场:Stage模型工程目录(DevEco Studio

当你用DevEco Studio创建一个新项目时,摆在你面前的是一套井然有序的目录结构,这就是你未来开发的主战场。理解每个目录的职责,就像搬进新家之前先熟悉卧室、厨房和客厅的位置。这套结构基于华为主推的Stage模型构建,它采用模块化设计理念,将应用程序拆分为多个独立模块,每个模块都有自己的生命周期和功能职责。Stage模型是高级认证考试中“应用程序框架”知识模块的核心内容之一。

从顶层俯瞰,你的项目主要包含以下几个核心部分。

最外层的AppScope目录存放应用全局所需的资源与配置。其中的app.json5文件声明了应用的全局信息,比如Bundle名称(即应用的唯一标识)、应用名称、图标和版本号。而AppScope/resources目录则存放应用级的公共资源文件,如图片、字符串等,这些资源可以被所有模块共享使用。

紧挨着的是entry目录,这是应用的功能入口模块,也是你绝大多数代码的所在地。编译构建时,entry目录会生成一个.hap文件(HarmonyOS Ability Package),这是应用在设备上独立安装和运行的基本单元。

在高级认证的编程考试中,你需要在规定时间内使用DevEco Studio完成指定项目的开发,熟悉entry目录的结构和用途是高效编码的前提。entry目录内部包含src/main/ets用于存放ArkTS源码,src/main/resources用于存放该模块专用的资源文件,以及module.json5这个模块级配置文件,它声明了该模块的基本信息、支持的设备类型、所含的组件以及运行所需申请的权限。

除此之外,项目根目录还有几个重要文件。build-profile.json5是应用级的构建配置文件,包括签名和产品配置;hvigorfile.ts是编译构建任务脚本,可以自定义构建行为;oh-package.json5则用于管理三方依赖库的信息。这些目录和文件共同构成了你的开发坐标系,熟悉它们的位置,后续开发就能做到心中有数。在高级认证的理论考试中,关于应用工程结构、模块配置文件的考点经常以选择题形式出现,因此从一开始就建立清晰的文件结构认知,对你后续备考也大有裨益。

认识你的语言:ArkTS与声明式UI

在鸿蒙开发中,ArkTS是主力应用开发语言。它并非凭空创造的全新语言,而是基于TypeScript进行了“鸿蒙化”扩展。学习ArkTS,核心需要掌握两个层面的内容:一是TypeScript的语法基础(如类型、接口、类、模块等),二是在此之上扩展的声明式UI能力。高级认证考试对ArkTS的要求不止于基础语法,还涉及ArkTS原理和实践层面的深度理解。

声明式UI是ArkTS区别于普通TypeScript最显著的特征。它的核心理念可以用两句话概括:开发者只需描述界面在不同状态下要呈现的最终效果,而无需关注界面变化的具体过程;界面的更新由状态数据驱动,开发者只需修改状态变量的值,界面就会自动刷新。这与传统的命令式UI(比如通过JavaScript直接操作DOM节点)形成了鲜明对比。

在命令式开发中,我们需要一步步指示每个UI元素的创建、属性设置和关系建立,如同精密的机械操作手册;而声明式UI则遵循“描述即实现”的理念,开发者仅需声明UI的最终状态与交互意图,具体实现交由框架处理。

从代码量的角度对比更为直观。以创建包含文本与按钮的交互界面为例,传统的命令式实现需要对象实例化、属性配置、事件绑定等多个步骤,而在ArkTS中,通过链式调用和声明式语法,代码量可减少60%以上。这种效率提升在高强度的编程考试中尤为重要——你需要在1小时内完成复杂页面的开发,更简洁的代码意味着更多时间用于功能实现和调试。

在ArkTS中,声明式UI的基本组成包括以下几个要素:

装饰器:用于装饰类、结构、方法或变量,赋予其特殊含义。最常用的有:@Entry表示该自定义组件为页面的入口组件,会在页面加载时首先渲染;@Component表示这是一个自定义组件,可被复用;@State表示该变量是状态变量,当它的值变化时会触发UI刷新。理解这些装饰器的作用和适用场景,是高级认证考试中“ArkTS声明式开发范式”模块的高频考点。

示例:

@Entry
@Component
struct DecoratorDemo {
  @State clickCount: number = 0

  build() {
    Column({ space: 20 }) {
      Text(`按钮被点击了 ${this.clickCount} 次`)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      Button('点我增加计数')
        .onClick(() => {
          this.clickCount++
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

这个例子完整展示了三个装饰器的协同作用。@Entry告诉系统这是一个页面入口,应用启动时会首先渲染它。@Component将这个struct声明为一个可复用的自定义组件。

@State则让clickCount成为响应式状态变量——每次点击按钮,clickCount的值增加,界面上的Text组件会自动刷新显示最新的计数,你无需手动操作DOM或调用任何更新方法。

自定义组件:用struct关键字声明,配合@Component装饰器。一个自定义组件内部必须包含一个build()方法,用于描述该组件的UI结构。每个自定义组件都有自己的生命周期,如aboutToAppear()build()函数之前执行,aboutToDisappear()在组件销毁时执行。

示例:

@Component
struct ChildComponent {
  @State value: number = 0

  // 生命周期:在build()执行之前调用,适合做初始化操作
  aboutToAppear() {
    console.info('子组件即将出现,初始化value为100')
    this.value = 100
  }

  // 生命周期:在组件销毁时调用,适合做清理操作
  aboutToDisappear() {
    console.info('子组件即将销毁,执行清理工作')
  }

  build() {
    Text(`来自子组件的值: ${this.value}`)
      .fontSize(20)
      .fontColor(Color.Blue)
  }
}

@Entry
@Component
struct LifecycleDemo {
  @State showChild: boolean = true

  build() {
    Column({ space: 30 }) {
      if (this.showChild) {
        ChildComponent()
      }

      Button(this.showChild ? '隐藏子组件' : '显示子组件')
        .onClick(() => {
          this.showChild = !this.showChild
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

这个例子包含两个自定义组件。ChildComponent展示了生命周期的用法:aboutToAppear()在UI渲染前执行,适合进行数据初始化、订阅事件等操作;aboutToDisappear()在组件被移除时执行,适合取消订阅、释放资源等清理工作。

LifecycleDemo通过一个按钮控制ChildComponent的创建和销毁,你可以在Log窗口(底部“Log”或“Run”面板)中观察到生命周期钩子的打印信息,直观理解它们的触发时机。

系统组件:ArkUI框架内置的基础UI单元,比如TextButtonImage等,可以直接在build()方法中调用。高级认证要求开发者掌握从简单页面到复杂页面的组件使用能力,包括导航组件(如Video、CustomDialog、Navigator等)的使用。

示例:

@Entry
@Component
struct SystemComponentDemo {
  @State showDialog: boolean = false

  build() {
    Column({ space: 20 }) {
      // Text组件:显示文本内容
      Text('这是Text组件')
        .fontSize(28)
        .fontColor(Color.Red)
        .fontWeight(FontWeight.Bold)

      // Button组件:可交互的按钮
      Button('点击弹出对话框')
        .onClick(() => {
          this.showDialog = true
        })

      // Image组件:显示图片资源
      Image($r('app.media.icon'))
        .height(80)
        .width(80)
        .borderRadius(16)

      // 导航组件:CustomDialog(自定义对话框)
      if (this.showDialog) {
        CustomDialog({
          title: '提示',
          message: '这是一个自定义对话框',
          confirm: () => {
            this.showDialog = false
          },
          cancel: () => {
            this.showDialog = false
          }
        })
      }

      // 导航组件:Navigator(页面跳转)
      Navigator({ target: 'pages/OtherPage' }) {
        Text('跳转到其他页面')
          .fontSize(18)
          .fontColor(Color.Blue)
          .padding(10)
          .border({ width: 1, color: Color.Blue })
          .borderRadius(8)
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

这个示例集中展示了ArkUI框架中最常用的几个系统组件。Text是最基础的文本显示单元,支持字体大小、颜色、粗细等丰富的样式配置。

Button是用户交互的核心组件,通过onClick事件绑定点击响应逻辑。Image用于显示本地或网络图片,这里示范了引用entry/src/main/resources/base/media目录下图片资源的标准写法。

CustomDialog是系统提供的对话框组件,适合用于提示、确认等简单弹窗场景。Navigator则实现了页面间跳转,target属性指定目标页面的路径,当用户点击其内部的子组件时触发跳转。在实际开发中,系统组件远不止这些,还包括ListGridScrollSwiper等,高级认证考试要求你熟练掌握这些组件的使用场景和配置方法。

属性方法和事件方法:组件可以通过链式调用的方式配置属性(如.fontSize(50).width(100))和绑定事件(如.onClick(() => {...}))。在高级认证的编程考试中,正确使用属性方法配置界面样式、使用事件方法实现用户交互,是评分的重要维度。

示例:

@Entry
@Component
struct MethodChainDemo {
  @State bgColor: string = '#FFFFFF'

  build() {
    Column() {
      Text('属性方法链式调用')
        .fontSize(22)                          // 设置字体大小
        .fontWeight(FontWeight.Medium)         // 设置字体粗细
        .fontColor(Color.White)                // 设置文字颜色
        .backgroundColor('#007AFF')            // 设置背景色
        .padding({ left: 20, right: 20, top: 12, bottom: 12 })  // 设置内边距
        .borderRadius(12)                      // 设置圆角
        .margin({ bottom: 30 })                // 设置外边距

      Text('点击下面按钮改变背景色')
        .fontSize(18)
        .margin({ bottom: 20 })

      Row({ space: 20 }) {
        Button('红色')
          .onClick(() => {
            this.bgColor = '#FF3B30'           // 事件方法:点击时改变状态
          })

        Button('绿色')
          .onClick(() => {
            this.bgColor = '#34C759'
          })

        Button('蓝色')
          .onClick(() => {
            this.bgColor = '#007AFF'
          })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor(this.bgColor)             // 整个Column的背景色跟随状态变化
    .justifyContent(FlexAlign.Center)
    .animation({ duration: 300 })              // 属性方法:为背景色变化添加动画
  }
}

这个例子着重展示了链式调用的强大表达能力。属性方法通过点语法连续调用,可以为一个组件配置多个样式属性,代码结构清晰、可读性强。事件方法则通过onClick等回调函数绑定用户交互逻辑。

Column组件的backgroundColor(this.bgColor)将背景色与状态变量绑定,当点击不同颜色的按钮时,bgColor的值被更新,整个容器的背景色随之平滑变化,而.animation({ duration: 300 })这行代码为这个变化添加了300毫秒的过渡动画,提升了交互体验。

这正是属性方法与事件方法协同工作的典型场景——属性定义UI的最终呈现方式,事件响应用户操作并驱动状态变化,状态变化反过来又通过属性更新UI,形成完整的交互闭环。在高级认证的编程考试中,这种“状态驱动+链式配置”的编程模式是你必须熟练掌握的核心技能。

你的首行代码:声明式UI的呼吸

让我们从一个最简单的例子开始,感受ArkTS声明式UI的编写节奏。这个例子实现一个“开关灯”的交互效果,非常直观地展示了“状态驱动视图更新”的核心思想。这个示例虽小,却涵盖了高级认证编程考试中需要掌握的核心编程模式:状态管理、条件渲染、事件绑定与用户交互。

首先,创建一个新的项目,然后按照以下步骤编写代码。

在这个文件下面写代码:

第一步,定义界面状态。我们用一个布尔类型的变量isOpen来表示灯的开关状态,true为开灯,false为关灯。这个变量被@State装饰,表明它是一个状态变量——当它的值改变时,所有用到它的UI描述都会自动重新渲染。@State是高级认证考试中最常被考察的装饰器之一,它实现了组件内部状态的响应式驱动,当状态变更时,框架通过高效的Diff算法计算差异,仅更新变化的UI部分。

@State isOpen: boolean = false;

第二步,描述界面在不同状态下的显示效果。我们在build()方法中使用Column容器进行纵向布局,内部使用条件渲染if/else语法:当isOpentrue时显示开灯的图片,为false时显示关灯的图片。同时,在下方放置两个按钮,分别用于“关灯”和“开灯”。

@Entry
@Component
struct ControlLight {
  @State isOpen: boolean = false

  build() {
    Column({ space: 50 }) {
      // 条件渲染:根据isOpen状态显示不同图片
      if (this.isOpen) {
        Image('pages/imgs/light-on.png')
          .height(300)
          .width(300)
      } else {
        Image('pages/imgs/light-off.png')
          .height(300)
          .width(300)
      }

      Row({ space: 50 }) {
        Button('关灯')
          .onClick(() => {
            this.isOpen = false
          })
        Button('开灯')
          .onClick(() => {
            this.isOpen = true
          })
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

如果没有图片的话可以使用

@Entry
@Component
struct Index {
  @State isOpen: boolean = false

  build() {
    Column({ space: 50 }) {
      // 使用Emoji或Text组件替代图片
      Text(this.isOpen ? '💡' : '🔌')
        .fontSize(200)
        .textAlign(TextAlign.Center)

      Row({ space: 50 }) {
        Button('关灯')
          .onClick(() => {
            this.isOpen = false
          })
        Button('开灯')
          .onClick(() => {
            this.isOpen = true
          })
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

关于代码中的布局细节,有几个要点值得深入理解。Column容器默认将子组件垂直排列,我们通过{ space: 50 }设置了子组件之间的间距,使图片与按钮之间有适当的留白。Row容器则水平排列两个按钮,{ space: 50 }让两个按钮之间保持合理距离。

justifyContent(FlexAlign.Center)的作用是让子组件在主轴方向(Column为垂直方向,Row为水平方向)上居中对齐,这样整个界面就在屏幕中央呈现。width('100%')height('100%')使容器占满父组件的全部可用空间。这些布局属性的组合使用,是高级认证编程考试中构建复杂页面的基础。

运行前请别忘记选择设备:

第三步,通过交互改变状态。两个按钮分别绑定了onClick事件,点击“开灯”按钮将isOpen设为true,点击“关灯”按钮将isOpen设为false。当你保存代码并运行,点击按钮时,图片会立即切换——这就是声明式UI最直观的反馈:你修改状态,界面自动响应。在高级认证的编程考试中,你需要用类似的方式实现复杂的用户交互逻辑,可能涉及多组件间的事件传递、状态同步等场景。

运行结果就是:

这个简单的例子虽然只有几十行代码,但它完整呈现了ArkTS声明式UI的开发流程:定义状态 → 描述UI → 改变状态 → 界面自动更新。这个闭环是你未来开发所有复杂功能的基础单元。当你建立起“我要实现什么效果 → 我定义什么状态 → 我如何描述UI → 我如何改变状态”的思维习惯后,后续学习组件库、布局、网络请求、数据持久化等高级特性,都只是在这个模式上不断添砖加瓦。

从第一课到高级认证之路

作为本系列的开篇,这一课的核心任务不是教你背诵语法规则,而是帮你建立开发坐标系——理解代码写在哪里、如何组织、以及最基本的交互逻辑如何实现。这是通往高级认证的第一步。

基于高级认证的考试大纲,后续课程将系统覆盖以下核心模块:应用程序框架(UIAbility生命周期、页面路由与数据传递)、ArkUI高级组件开发(复杂页面构建、自定义组件封装)、网络与数据管理(HTTP请求、用户首选项、分布式数据库)、多设备协同与一次开发多端部署、端云一体化开发等。每个模块都将沿用本课的“理论+实操”模式,确保在学习知识的同时,积累足够的上手经验以应对编程考试。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐