
适用版本:HarmonyOS 5.0.0+ / ArkTS API 12+
难度:入门级
预计阅读时间:25 分钟
配套代码:见文末工程目录
写在前面
这篇笔记的目标很简单------在你初步了解 ArkTS 语法之后,用一个能跑起来的完整示例,把 ArkTS 写 UI 的"基本套路"一次性讲清楚。
示例的效果很直观:页面上有一个大标题显示 "Hello World",点击按钮后,标题变成 "Hello ArkUI",同时颜色从灰色变为蓝色。这个看似简单的交互,背后包含了 ArkTS 声明式 UI 开发的核心要素。
一、最终效果与工程结构
1.1 运行效果
启动应用后,屏幕中央显示 "Hello World" ,下方有一个蓝色按钮。点击按钮,文本瞬间变为 "Hello ArkUI",颜色同步切换为蓝色。
除了这个基础示例外,本文还扩展了三个进阶用法示例页面,分别展示 @Builder/@BuilderParam、@Extend/@Styles 和 stateStyles 的实际效果。




1.2 工程目录
ArkTS基础入门/
├── entry/src/main/ets/pages/
│ ├── Index.ets # 主页面:Hello World → Hello ArkUI
│ ├── BuilderPage.ets # @Builder/@BuilderParam 示例
│ ├── StylesPage.ets # @Extend/@Styles 示例
│ └── StateStylesPage.ets # stateStyles 多态样式示例
└── preview.html # 网页预览(模拟真机效果)
二、核心代码逐行拆解
下面是 Index.ets 的完整代码,我会逐段解释每一行在做什么。
typescript
import { router } from '@kit.ArkUI';
@Entry
@Component
struct Hello {
@State message: string = 'Hello World';
@State isChanged: boolean = false;
build() {
Column({ space: 20 }) {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.fontColor(this.isChanged ? '#007DFF' : '#333333')
Divider()
.strokeWidth(2)
.color('#E5E5E5')
.width('80%')
Button('点击切换文本')
.fontSize(20)
.width('60%')
.height(50)
.backgroundColor('#007DFF')
.onClick(() => {
this.message = 'Hello ArkUI';
this.isChanged = true;
})
Button('查看 @Builder/@BuilderParam 示例')
.fontSize(16)
.width('80%')
.height(44)
.backgroundColor('#00C7BE')
.margin({ top: 40 })
.onClick(() => {
router.pushUrl({ url: 'pages/BuilderPage' });
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#F5F5F5')
}
}
2.1 装饰器:@Entry、@Component、@State
typescript
@Entry
@Component
struct Hello {
@Entry:标记这个组件是应用的入口页面。每个.ets文件中最多只能有一个@Entry装饰的组件。@Component:标记这是一个自定义组件。所有 UI 组件都必须用@Component装饰。struct Hello:struct是 ArkTS 中定义组件结构体的关键字,Hello是这个组件的名字。
typescript
@State message: string = 'Hello World';
@State isChanged: boolean = false;
@State:状态装饰器。被@State装饰的变量是"状态变量"------当它的值发生变化时,ArkUI 会自动重新渲染依赖这个变量的 UI 部分。
关键理解: 在 ArkTS 里,你不需要手动调用 "刷新页面" 的 API。只要 @State 变量的值变了,系统会自动找出哪些 UI 元素依赖了它,然后只更新那些部分。
重要约束: 自定义变量不能与基础通用属性/事件名重复。
2.2 UI 描述:build() 方法
typescript
build() {
Column({ space: 20 }) {
// ...
}
}
build() 是每一个 @Component 组件必须实现的方法。它的返回值就是组件的 UI 结构。ArkTS 用声明式语法描述 UI------你写的不是"一步步创建控件"的命令,而是"这个页面长什么样"的描述。
2.3 系统组件:Column、Text、Divider、Button
typescript
Text(this.message)
Column:垂直排列的容器组件。{ space: 20 }表示子组件之间的间距为 20vp。Text:文本显示组件。括号里传入要显示的字符串。Divider:分割线组件。Button:按钮组件。括号里传入按钮上的文字。
这些都是 ArkUI 框架内置的系统组件,开箱即用。
2.4 属性方法:链式调用配置样式
typescript
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.fontColor(this.isChanged ? '#007DFF' : '#333333')
每个系统组件都可以通过链式调用配置属性:
.fontSize(50):字体大小 50fp.fontWeight(FontWeight.Bold):粗体.fontColor(...):字体颜色。这里用了一个三元表达式------如果isChanged为 true,显示蓝色#007DFF,否则显示深灰色#333333
链式调用的本质: 每个属性方法都返回组件自身,所以可以连续 . 下去。这种写法比传统的"设置属性"更紧凑,也更符合声明式 UI 的思维。
2.5 事件方法:onClick
typescript
Button('点击切换文本')
.onClick(() => {
this.message = 'Hello ArkUI';
this.isChanged = true;
})
.onClick() 是给按钮绑定点击事件。当用户点击按钮时,回调函数被执行:
this.message = 'Hello ArkUI':修改状态变量this.isChanged = true:修改另一个状态变量
因为这两个变量都被 @State 装饰,ArkUI 会自动检测到变化,然后重新渲染 Text 组件------文本内容从 "Hello World" 变为 "Hello ArkUI",颜色从灰色变为蓝色。
三、扩展语法范式实战
除了基础的装饰器、组件、属性、事件之外,ArkTS 还提供了几种语法范式,让代码复用和样式管理更高效。
3.1 @Builder / @BuilderParam:封装复用 UI 描述
@Builder 可以把一段 UI 描述封装成方法,在多处复用。
typescript
@Builder
HeaderText(content: string) {
Text(content)
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 20 })
}
使用的时候直接调用:
typescript
this.HeaderText('这是标题')
@Builder 还可以接收参数,实现更灵活的复用。上面的 HeaderText 接收一个 content 参数,调用时传入不同的字符串,就能生成不同内容的标题。
@BuilderParam 则用于"向组件传入一段 UI"。比如一个卡片组件,它的内容区域可能是图片、文字、或者图表------用 @BuilderParam 可以让调用方自由定义这部分 UI。
typescript
@Component
struct CustomCard {
@BuilderParam
content: () => void
build() {
Column() {
// 卡片头部固定
Text('卡片标题').fontSize(18)
// 内容区域由外部传入
this.content()
}
}
}
3.2 @Extend / @Styles:统一组件样式
@Extend 用于给系统组件"打补丁"------定义一组默认属性,任何使用该组件的地方都能一键套用。
typescript
@Extend(Text)
function CardTitle() {
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
使用方式:
typescript
Text('文章标题').CardTitle()
@Styles 用于封装通用属性样式(如 width、height、padding、margin、backgroundColor 等),但它只能封装"通用属性",不能封装组件特有属性(如 Text 的 fontSize)。
typescript
@Styles
cardStyle() {
.width('90%')
.padding(20)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 8, color: 'rgba(0,0,0,0.08)', offsetY: 2 })
}
使用方式:
typescript
Column() {
// ...
}.cardStyle()
@Extend 和 @Styles 的核心区别:
| 特性 | @Extend | @Styles |
|---|---|---|
| 目标 | 特定系统组件(Text、Button 等) | 通用属性 |
| 能否使用组件特有属性 | 能(如 fontSize、fontWeight) | 不能 |
| 使用方式 | .FunctionName() |
.functionName() |
| 参数支持 | 支持 | 不支持 |
3.3 stateStyles:多态样式
stateStyles 让组件能根据内部状态(normal、pressed、disabled、focused)自动切换样式。
typescript
Button('按压变色按钮')
.stateStyles({
normal: {
.backgroundColor('#007DFF')
.scale({ x: 1, y: 1 })
},
pressed: {
.backgroundColor('#0056B3')
.scale({ x: 0.96, y: 0.96 })
},
disabled: {
.backgroundColor('#CCCCCC')
.opacity(0.6)
}
})
上面的代码定义了三种状态样式:
- normal:正常状态,蓝色背景,正常大小
- pressed:按压状态,深蓝色背景,略微缩小(96%)
- disabled:禁用状态,灰色背景,透明度 60%
用户手指按上去时,按钮自动切换到 pressed 样式;手指抬起时,自动回到 normal。如果通过 .enabled(false) 禁用按钮,则自动显示 disabled 样式。
四、动手验证
4.1 在 DevEco Studio 中运行
- 打开 DevEco Studio,新建一个 Empty Ability 工程
- 将
Index.ets替换为本文提供的代码 - 将
BuilderPage.ets、StylesPage.ets、StateStylesPage.ets放入entry/src/main/ets/pages/目录 - 在
resources/base/profile/main_pages.json中注册所有页面:
json
{
"src": [
"pages/Index",
"pages/BuilderPage",
"pages/StylesPage",
"pages/StateStylesPage"
]
}
- 点击运行,在模拟器或真机上查看效果
4.2 网页预览
如果你没有 DevEco Studio 环境,也可以直接用浏览器打开工程目录下的 preview.html,在网页上模拟真机交互效果。
五、常见新手问题
Q:为什么修改了普通变量(没有用 @State),UI 没有更新?
A:只有被 @State、@Prop、@Link 等状态装饰器修饰的变量发生变化时,ArkUI 才会触发 UI 刷新。普通变量的修改对 UI 无影响。
Q:@Extend 和 @Styles 应该选哪个?
A:如果是给某个系统组件(如 Text、Button)定义一组常用样式,用 @Extend。如果是封装通用的布局属性(如卡片的宽度、内边距、圆角),用 @Styles。两者可以混用。
Q:stateStyles 支持哪些状态?
A:目前支持 normal(正常)、pressed(按压)、disabled(禁用)、focused(聚焦)四种状态。不同组件支持的状态可能不同,Button 支持全部四种,TextInput 主要用 normal 和 focused。
Q:自定义变量名可以和系统属性重名吗?
A:不可以。自定义变量不能与基础通用属性/事件名重复,否则会导致编译错误或行为异常。
六、总结
通过这一个示例,你已经接触到了 ArkTS 声明式 UI 开发的全部基本要素:
| 概念 | 作用 | 示例 |
|---|---|---|
| @Entry / @Component | 定义入口组件 | @Entry @Component struct Hello |
| @State | 声明状态变量 | @State message: string = 'Hello World' |
| build() | 描述 UI 结构 | build() { Column() { ... } } |
| 系统组件 | 内置 UI 元素 | Column、Text、Button、Divider |
| 属性方法 | 配置组件样式 | .fontSize(50)、.backgroundColor('#007DFF') |
| 事件方法 | 响应用户交互 | .onClick(() => { ... }) |
| @Builder | 封装复用 UI 描述 | @Builder HeaderText(content: string) { ... } |
| @Extend | 扩展系统组件样式 | @Extend(Text) function CardTitle() { ... } |
| @Styles | 封装通用属性 | @Styles cardStyle() { ... } |
| stateStyles | 多态样式切换 | .stateStyles({ normal: {...}, pressed: {...} }) |
掌握这些,你就已经跨过了 ArkTS UI 开发的"第一道门槛"。剩下的,就是在实际项目中不断组合、扩展这些基础能力。