4. ArkUI框架入门:ArkUI设计理念、声明式UI、组件化开发、页面布局基础

ArkUI 是 OpenHarmony 的原生 UI 框架。说白了,它就是用来搭界面的。我刚开始接触的时候,第一反应是「这不就是 Flutter 那套吗?」—— 确实有相似之处,但 ArkUI 的设计更贴近鸿蒙的分布式场景。今天咱们就把它的核心脉络理清楚。

4.1 ArkUI 的设计理念:从「命令」到「描述」

传统 Android 开发里,你要先 findViewById,再 setText,再 setOnClickListener —— 每一步都是「命令」。ArkUI 换了个思路:你只需要「描述」界面长什么样,剩下的框架帮你搞定。

核心转变:

  • 命令式 UI:「给我找到这个按钮,把它的文字改成'提交',再给它加个点击事件」
  • 声明式 UI:「这个按钮的文字是'提交',点击时执行这个函数」

你想想看,哪种方式更直观?我在项目里带新人时,发现他们学声明式 UI 反而更快 —— 因为不用记那些繁琐的 API 调用顺序,直接写布局就行。

4.2 声明式 UI:状态驱动视图

声明式 UI 的核心是「状态驱动」。什么意思?界面不是手动刷新的,而是跟着数据走。

@State message: string = 'Hello ArkUI'

build() {
  Column() {
    Text(this.message)
      .fontSize(30)
    Button('点击更新')
      .onClick(() => {
        this.message = '状态变了!'
      })
  }
}

看到没?@State 标记了 message 是「响应式状态」。当它改变时,Text 组件自动重新渲染。你不需要手动调用 setText 或 invalidate。

我的习惯:所有需要动态变化的变量,第一时间加上 @State。哪怕一开始是静态的,后续需求变更时也少改一次代码。

为什么会这样设计?因为分布式场景下,状态可能来自手机、平板、甚至传感器。手动刷新太容易出错了。声明式 UI 让开发者只关注「数据长什么样」,不关心「怎么画到屏幕上」。

4.3 组件化开发:搭积木的艺术

ArkUI 里一切皆组件。一个页面就是一棵组件树。

ArkUI 组件树结构 Page (页面) Column (列容器) Row (行容器) Text (文本) Button (按钮) Image (图片) Input (输入框) 组件化开发要点 每个组件只负责自己的 UI 和逻辑 通过 @Prop / @Link 实现父子通信

组件化开发的好处很明显:

  • 复用:写好的组件到处用,不用重复造轮子
  • 隔离:改一个组件不影响其他部分
  • 测试:每个组件可以单独验证

我曾经踩过的坑:一开始把所有逻辑都塞在一个大组件里,结果改一个按钮样式要翻几百行代码。后来强制自己按功能拆成小组件,每个组件不超过 100 行。维护成本直线下降。

4.4 页面布局基础:Flex 与栅格

布局是 UI 的骨架。ArkUI 提供了几种核心布局容器,我挑最常用的两个讲。

4.4.1 Flex 布局:弹性伸缩

Flex 布局适合一维排列(行或列)。

Flex({
  direction: FlexDirection.Row,  // 水平排列
  justifyContent: FlexAlign.SpaceBetween,  // 两端对齐
  alignItems: ItemAlign.Center  // 垂直居中
}) {
  Text('左')
  Text('中')
  Text('右')
}

我个人习惯把 Flex 当作「万能布局器」。遇到不确定怎么排的场景,先上 Flex,再调参数。90% 的情况都能搞定。

属性 可选值 作用
direction Row / Column / RowReverse / ColumnReverse 主轴方向
justifyContent Start / Center / End / SpaceBetween / SpaceAround / SpaceEvenly 主轴对齐方式
alignItems Start / Center / End / Stretch / Baseline 交叉轴对齐方式

4.4.2 栅格布局:响应式利器

如果你的应用要跑在手机、平板、折叠屏上,栅格布局是首选。

GridRow() {
  GridCol({ span: { xs: 12, sm: 6, md: 4, lg: 3 } }) {
    Text('卡片1')
  }
  GridCol({ span: { xs: 12, sm: 6, md: 4, lg: 3 } }) {
    Text('卡片2')
  }
}

这里 xs 对应小屏手机,lg 对应大屏平板。一行 12 列,span 表示占几列。你想想看,一套代码适配所有屏幕,是不是很省心?

避坑指南:栅格布局不要嵌套太深。我曾经为了追求完美布局,套了 5 层栅格,结果渲染性能直接崩了。一般 2-3 层就够了。

4.5 实战:搭建一个简单的个人名片页

光说不练假把式。咱们用刚学的知识搭一个名片页。

@Entry
@Component
struct CardPage {
  @State name: string = '张三'
  @State title: string = 'OpenHarmony 开发者'

  build() {
    Column({ space: 20 }) {
      // 头像区域
      Circle({ width: 80, height: 80 })
        .fill('#3498db')

      // 姓名和职位
      Text(this.name)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
      Text(this.title)
        .fontSize(16)
        .fontColor('#666666')

      // 联系方式
      Row({ space: 30 }) {
        Button('电话')
        Button('邮箱')
        Button('微信')
      }

      // 个人简介
      Text('专注 OpenHarmony 应用开发,热爱分享技术')
        .fontSize(14)
        .textAlign(TextAlign.Center)
        .padding(20)
    }
    .padding(30)
    .width('100%')
    .height('100%')
  }
}

这个例子用到了 Column、Row、Circle、Text、Button 等组件。布局上,外层是垂直排列,联系方式那行是水平排列。嗯,这里要注意 space 参数,它控制子组件之间的间距,比手动加 margin 方便多了。

本章核心要点:

  • ArkUI 是声明式 UI 框架,你描述「是什么」,框架管「怎么画」
  • @State 是响应式状态的核心,数据变了界面自动更新
  • 组件化开发要拆得细、拆得合理,每个组件职责单一
  • Flex 布局搞定一维排列,栅格布局搞定多屏适配