鸿蒙应用开发实战:从零学会自定义组件

这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。

一、引言

在鸿蒙应用开发中,随着项目功能的日益复杂,将所有代码都堆砌在一个文件里显然是不现实的。这不仅会让代码变得臃肿难读,更会给后期的维护和功能复用带来巨大挑战。

为了解决这个问题,鸿蒙提供了自定义组件这一核心机制。它允许我们将一个复杂的页面,按照功能模块拆分成若干个独立、可复用的小组件,然后再将它们像搭积木一样拼装起来,形成一个完整的应用。

二、为什么要使用自定义组件?

在动手编码之前,我们先来理解一下自定义组件的核心价值。以一个功能复杂的编辑器为例:

  • 模块化拆分:我们可以将编辑器拆分为"顶部工具栏"、"中间编辑区"、"底部状态栏"三个独立的部分。
  • 独立开发与维护:每个部分都是一个独立的组件,修改"顶部工具栏"的样式,完全不会影响到"中间编辑区"的逻辑。
  • 功能复用:如果另一个页面也需要一个类似的"底部状态栏",我们只需引入这个组件即可,无需重复编写代码。

这种"分而治之"的思想,是构建大型、可维护应用的基础。

三、实战:创建你的第一个自定义组件

下面,我们通过一个具体的案例,来演示如何创建和使用自定义组件。我们将创建一个包含 Header、Main 和 Footer 三个组件的页面。

3.1 项目结构准备

首先,我们需要在项目中创建一个合理的目录结构来存放组件。

  1. 在 pages 目录下,新建一个文件夹,命名为 day01,用于存放今天学习的代码。
  2. 在 day01 文件夹上右键,选择 New > Page,选择 Empty Page,并为其命名(例如 Index),点击 Finish 完成创建。
  3. 再次在 day01 文件夹上右键,选择 New > Directory,新建一个名为 components 的文件夹。
  4. 在 components 文件夹上右键,选择 New > ArkTS File,依次创建三个文件:Header.ets、Main.ets 和 Footer.ets。

3.2 编写自定义组件

接下来,我们分别编写这三个组件。

1. Header 组件 (Header.ets)

双击打开 Header.ets 文件,输入 @Component 后按回车键,IDE 会自动生成组件的基本结构。然后,我们为其添加一个简单的文本。

typescript 复制代码
@Component
struct Header {
  build() {
    Text('这是 Header 组件')
      .fontSize(20)
      .height(50)
      .width('100%')
      .backgroundColor('#FFA500')
      .textAlign(TextAlign.Center)
  }
}

注意 :自定义组件上不要 添加 @Entry 装饰器,它只用于页面级组件。

2. Main 组件 (Main.ets)

按照同样的方式,编写 Main.ets 文件。

typescript 复制代码
@Component
struct Main {
  build() {
    Text('这是 Main 组件')
      .fontSize(20)
      .width('100%')
      .backgroundColor('#87CEEB')
      .textAlign(TextAlign.Center)
  }
}

3. Footer 组件 (Footer.ets)

编写 Footer.ets 文件。

typescript 复制代码
@Component
struct Footer {
  build() {
    Text('这是 Footer 组件')
      .fontSize(20)
      .height(50)
      .width('100%')
      .backgroundColor('#90EE90')
      .textAlign(TextAlign.Center)
  }
}

3.3 导出组件

为了让其他文件能够使用这些自定义组件,我们需要将它们导出。在每个组件文件的结构体定义前,加上 export default 关键字。

以 Header.ets 为例:

typescript 复制代码
export default struct Header {
  // ... 组件内容
}

请同样为 Main.ets 和 Footer.ets 添加 export default。

3.4 在主页面中引入并使用组件

现在,我们打开之前创建的页面文件(例如 Index.ets),将这三个组件组合起来。

  1. 删除页面中自动生成的示例代码。
  2. 在页面顶部,使用 import 语句引入这三个组件。
  3. 在 build() 方法中,使用一个 Column 容器将它们包裹起来。
typescript 复制代码
import Header from './components/Header'
import Main from './components/Main'
import Footer from './components/Footer'

@Entry
@Component
struct Index {
  build() {
    Column() {
      Header()
      Main()
      Footer()
    }
    .width('100%')
    .height('100%')
  }
}

3.5 预览效果

点击右上角的 Previewer 按钮,你就可以在预览器中看到,Header、Main 和 Footer 三个组件已经按照从上到下的顺序,被成功组合到了一个页面中。

四、进阶技巧:layoutWeight 与 @Preview

4.1 使用 layoutWeight 动态分配空间

在上面的例子中,我们为 Header 和 Footer 设置了固定的高度(50vp)。那么,Main 组件如何自动填满剩余的空间呢?

答案就是 layoutWeight 属性。它的作用是按比例动态分配子元素在父容器主轴方向上的剩余空间。

由于我们最外层是 Column 组件,其主轴方向是垂直的。因此,在 Main 组件中添加 .layoutWeight(1),它就会自动占满除去 Header 和 Footer 后的所有剩余空间。

修改 Main.ets 文件:

typescript 复制代码
@Component
export default struct Main {
  build() {
    Text('这是 Main 组件')
      .fontSize(20)
      .width('100%')
      .layoutWeight(1) // 添加这一行
      .backgroundColor('#87CEEB')
      .textAlign(TextAlign.Center)
  }
}

4.2 使用 @Preview 单独预览组件

当自定义组件逻辑变得复杂时,你可能希望在不运行整个页面的情况下,单独预览这个组件。鸿蒙提供了 @Preview 装饰器来实现这一点。

在你想预览的组件(例如 Main.ets)的结构体定义前,添加 @Preview 装饰器。

typescript 复制代码
@Preview
@Component
export default struct Main {
  // ... 组件内容
}

添加后,点击预览器,你就可以单独看到 Main 组件的渲染效果了,这大大提升了开发调试的效率。

五、总结

通过本文的实战,你已经掌握了鸿蒙自定义组件的核心用法:

  1. 创建 :通过 @Component 装饰器定义组件结构。
  2. 导出 :使用 export default 让组件可以被外部引用。
  3. 引入与使用 :在页面中通过 import 引入,并像使用普通组件一样使用它。
  4. 布局 :利用 layoutWeight 实现灵活的页面布局。
  5. 调试 :使用 @Preview 装饰器进行组件的独立预览。

自定义组件是构建复杂鸿蒙应用的基石,熟练掌握它将使你的开发效率和质量得到显著提升。现在,就开始在你的项目中实践吧!

相关推荐
桔筐11 分钟前
Vue中DOM的data-*自定义属性(dataset)与Vue data响应式变量区别详解
前端·javascript·vue.js
万物智能信息科技22 分钟前
气体传感器MQ-2芯片驱动开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
驱动开发·嵌入式硬件·华为·开源·harmonyos
懿路向前27 分钟前
HarmonyOS 粒子特效实战:ArkTS V2 状态管理三坑:@Local 判据 / 引用替换 / 双通道更新(HarmonyOS)
华为·harmonyos
小马过河R29 分钟前
EdgeOne深度解析:从原理、适用场景到COS接入的技术逻辑
java·开发语言·前端·spring·cos
ZoeLandia1 小时前
TypeScript 04:类型断言与类型守卫
开发语言·前端·typescript
guzicheng19901 小时前
webpack 安装笔记:全局 vs 本地,以及一个 PATH 环境变量的坑
前端·webpack
西索斯coding1 小时前
Claude Code 工具调用返回空怎么办?claude-opus-5.5 的 input_schema 校验踩坑记录与修复方案
服务器·前端·javascript·ai
疯狂敲代码的老刘1 小时前
MarvellousSuspender浏览器扩展:1.4K星开源标签页冻结神器,Chrome吃内存终结者的干净复活版
前端·chrome
码上上班1 小时前
shell 脚本知识点总结
前端·chrome
程序员Sunday1 小时前
Flex 和 Grid 有什么区别?一维布局、二维布局怎么选?
前端·css·面试