ArkUI 声明式UI开发入门:你还在“画界面”,还是在“描述状态”?

举报
bug菌 发表于 2025/12/25 17:15:55 2025/12/25
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8 😏 摘要来啦来啦😄!这一节我就用“不端着、讲人话”的方式,把 Ar...

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

😏 摘要

来啦来啦😄!这一节我就用“不端着、讲人话”的方式,把 ArkUI 声明式 UI 的入门要点掰开揉碎讲清楚——你会发现它不是“换个写法”,而是换了脑回路🧠✨:你不再“命令 UI 变成什么”,而是“描述状态长什么样,UI 自己跟着变”。

🧩 ArkUI 框架概述:声明式到底声明了个啥?🤔

先来一句特别接地气的理解:

  • 命令式 UI(老派)
    “你!Text 去 setText,Button 去 setEnabled,列表去 notifyDataSetChanged!”😤
    ——像指挥一群小朋友排队,累死你还不一定听话。

  • 声明式 UI(ArkUI)
    “当 count=3 的时候,界面就长这样;当 count=0 的时候,界面就长那样。”🙂
    ——你写的是规则,UI 是规则的结果

ArkUI 的核心心法就一句:

UI = f(state)
状态(state)变了,UI 自然跟着重建/更新。你不用满屏找控件引用,省心到想给自己鼓掌👏。

🧱 组件化开发:别把页面写成一锅粥🍲

很多新手写 UI 的姿势是:一个页面 500 行起步,翻起来像看《红楼梦》📚(还没目录那种)。
组件化能救命,真的。

✅ 组件化的“人类友好”原则(我常用)

  • 页面只做“编排”和“路由”,别塞业务逻辑
  • 可复用的 UI 抽组件(卡片、标题栏、空状态、列表项)
  • 数据从上往下传,事件从下往上冒(别乱飞)

下面我们先把装饰器搞明白,再上组件拆分示例😎。

🏷️ @Component / @Entry 装饰器:谁是入口?谁是演员?🎬

你可以把它们想成拍戏:

  • @Entry:主角登场🎤(应用/页面入口,系统先找它)
  • @Component:演员/配角🧑‍🎤(可复用组件,负责某一块 UI)

一般一个页面文件里:页面组件会同时带 @Entry + @Component(作为入口页面)。
而你抽出来的小组件通常只需要 @Component

🧪 基本组件:Text、Button、Image(先把“锅铲”拿稳🍳)

下面我用一个迷你计数器 + 图标展示的小例子,把 Text/Button/Image 串起来。
你能直接拿去跑、再改成自己的页面结构。

🧷 示例:计数器 + 图片 + 交互(超基础但很实用)

// CounterPage.ets
@Entry
@Component
struct CounterPage {
  @State count: number = 0

  build() {
    Column({ space: 12 }) {
      Text('🧮 ArkUI 计数器')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      Text(`当前数值:${this.count}`)
        .fontSize(18)

      Row({ space: 10 }) {
        Button('➖ 减一')
          .onClick(() => {
            if (this.count > 0) this.count--
          })

        Button('➕ 加一')
          .onClick(() => {
            this.count++
          })
      }

      // Image 通常加载资源文件(示例写法,按你的资源路径/工程配置调整)
      Image($r('app.media.icon'))
        .width(64)
        .height(64)
        .borderRadius(12)

      // 一个小彩蛋:状态驱动 UI 的直观体现
      if (this.count === 0) {
        Text('😴 还没开始呢,点一下加一试试?')
          .fontColor('#888')
      } else {
        Text('🔥 有感觉了!状态变了,UI 真的跟着变!')
          .fontColor('#888')
      }
    }
    .padding(16)
  }
}

👀 你看,声明式“爽点”在哪?

  • 你没有去找 TextView,也没有 setText()
  • 你只改了 this.count,UI 自己就变了
    这就像你调了空调温度,房间自己变凉——你不需要拿扇子给每个人扇风😅。

🧰 组件拆分实战:把“重复 UI”关进笼子🪤

现在我们把上面的 UI 拆出一个可复用组件,比如一个“数值显示卡片”。

✅ 可复用组件:CountCard

// CountCard.ets
@Component
export struct CountCard {
  @Prop title: string
  @Prop value: number

  build() {
    Column({ space: 6 }) {
      Text(this.title)
        .fontSize(16)
        .fontColor('#666')

      Text(`${this.value}`)
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
    }
    .padding(12)
    .borderRadius(12)
    .backgroundColor('#F5F5F5')
  }
}

✅ 页面里使用它(组合起来就完事儿😎)

// CounterPage.ets
import { CountCard } from './CountCard'

@Entry
@Component
struct CounterPage {
  @State count: number = 0

  build() {
    Column({ space: 12 }) {
      Text('🧩 组件化示例')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      CountCard({ title: '当前数值', value: this.count })

      Row({ space: 10 }) {
        Button('➖').onClick(() => { if (this.count > 0) this.count-- })
        Button('➕').onClick(() => { this.count++ })
      }
    }
    .padding(16)
  }
}

你会发现:页面突然变“干净”了,读起来像菜单,而不是像施工图纸🧱。

🧱 布局容器:Column / Row / Stack(站队、横排、叠罗汉🙃)

布局这块我特别想说一句:
很多 UI 崩坏,不是因为你不会组件,而是你布局容器用得太随缘😂。

📌 Column:竖着排(从上到下)

适合:表单、列表页结构、上下分区。

Column({ space: 8 }) {
  Text('上')
  Text('中')
  Text('下')
}
.padding(16)

常用点:

  • space:子组件间距
  • padding():内边距
  • layoutWeight():抢空间(常用于撑满剩余区域)

📌 Row:横着排(从左到右)

适合:按钮组、标题栏、左右布局。

Row({ space: 10 }) {
  Button('左')
  Button('右')
}
.padding(16)

小建议(我踩坑踩出来的😭):
Row 里如果一边内容很长,记得用 layoutWeight(1) 给它空间,不然它会被挤成“委屈巴巴的一条线”。

📌 Stack:叠着放(层叠/覆盖)

适合:角标、蒙层、背景图 + 前景内容。

Stack() {
  Image($r('app.media.banner'))
    .width('100%')
    .height(160)

  Text('📌 叠在图片上的标题')
    .fontSize(20)
    .fontColor('#FFFFFF')
    .margin({ top: 12, left: 12 })
}
.borderRadius(12)
.clip(true)

Stack 就像叠罗汉🤹:先放的在下面,后放的在上面。
用它做“卡片角标”“遮罩提示”特别香✨。

🧯 入门阶段最容易翻车的 5 个点(避坑版🥲)

  1. 把所有逻辑都写在 build 里
    build 里尽量只做 UI 描述,复杂逻辑抽方法/服务层。

  2. 状态乱放
    UI 瞬时态用 @State,跨组件传值用 @Prop,别把一切都塞 State。

  3. 组件过度“巨无霸”
    一个组件 300 行,后面你自己都不爱维护(别问我怎么知道😅)。

  4. Row/Column 不会分配空间
    记住:该用 layoutWeight(1) 的地方别抠门。

  5. Stack 忘记裁剪
    圆角卡片里放图,记得 clip(true),不然圆角是假圆角🙂。

✅ 小结:你现在至少应该掌握这些😄

  • ArkUI 声明式:状态驱动 UI
  • @Entry:入口;@Component:组件
  • Text/Button/Image:基础控件能写出完整交互
  • Column/Row/Stack:三板斧布局能搞定 80% 页面
  • 组件化:让你的代码从“能跑”进化到“能活”🐣➡️🦅

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。