
ArkUI 声明式开发组件与构建器ArkUI 是鸿蒙的声明式 UI 框架。它用描述界面长什么样替代一步步操作视图配合状态驱动自动刷新。本文系统讲清 ArkUI 的组件体系、内置组件、自定义组件、Builder/Styles/Extend复用手段以及组件生命周期帮你写出结构清晰、可复用的界面。一、声明式 UI 的核心思想传统命令式 UI如早期 AndroidfindViewByIdsetText是拿到控件、手动改它声明式 UI 是根据状态描述界面应有的样子。当状态变化框架自动计算差异并重绘。ArkUI 的三要素组件ComponentUI 的最小单元如Text、Button、Image。属性Attribute通过链式调用配置组件如.fontSize(20)。状态State被State等装饰的变量变化触发 UI 刷新。Entry Component struct Index { State liked: boolean false; build() { Column() { Text(this.liked ? 已点赞 : 未点赞) Button(this.liked ? 取消 : 点赞) .onClick(() { this.liked !this.liked; }) } } }你只声明了文本随 liked 变化点击后框架自动更新——这就是声明式的威力。二、内置基础组件ArkUI 提供丰富内置组件常用的有组件用途Text文本Button按钮Image图片TextInput输入框Toggle开关Progress进度条Slider滑块List/ListItem列表Grid/GridItem网格Scroll滚动容器文本与按钮Text(鸿蒙) .fontSize(20) .fontColor(#333) .lineHeight(28) .textAlign(TextAlign.Center) Button(提交, { type: ButtonType.Capsule }) .width(120) .height(40) .backgroundColor(#0A59F7) .onClick(() { /* 处理点击 */ })输入框带双向绑定State keyword: string ; TextInput({ placeholder: 搜索 }) .onChange((v: string) { this.keyword v; }) Text(你输入了 this.keyword)三、图片组件 ImageImage支持本地资源、网络、PixelMap、SVG// 本地资源$r 引用 resources/media Image($r(app.media.banner)) .width(200) .height(120) .borderRadius(8) .objectFit(ImageFit.Cover) // 网络图片需 ohos.permission.INTERNET Image(https://example.com/a.png) .width(100) .height(100) .onComplete(() { console.info(加载完成); }) .onError(() { console.error(加载失败); }).objectFit控制填充方式Cover裁剪填满、Contain完整显示、Fill拉伸。四、列表与懒加载ListForEach是展示集合数据的主力虚拟滚动只渲染可视区域性能极佳interface Item { id: number; name: string; } Entry Component struct ListPage { State data: Item[] [ { id: 1, name: 商品A }, { id: 2, name: 商品B } ]; build() { List({ space: 10 }) { ForEach(this.data, (item: Item) { ListItem() { Row() { Text(item.name).fontSize(16) } .padding(12) .backgroundColor(#FFF) .borderRadius(8) } .onClick(() { console.info(点击 item.name); }) }, (item: Item) item.id.toString()) // 第二参唯一 key性能关键 } .width(100%) .height(100%) .padding(12) } }ForEach的第三个参数是键值生成函数返回稳定唯一 key 才能正确复用节点、避免错乱——这是 ArkUI 性能优化的关键点。五、自定义组件把一段 UI 封装成Component结构体接受Prop入参Component struct ProductCard { Prop product: Item { id: 0, name: }; State pressed: boolean false; build() { Column() { Text(this.product.name).fontSize(16).fontWeight(FontWeight.Medium) Button(加入购物车) .margin({ top: 8 }) .onClick(() { this.pressed true; }) } .width(100%) .padding(16) .backgroundColor(this.pressed ? #E8F0FE : #FFF) .borderRadius(12) } } // 使用 Column() { ForEach(this.data, (it: Item) { ProductCard({ product: it }) }) }自定义组件让页面像搭积木一样组合复杂界面也能保持可读。六、BuilderUI 片段复用Builder用于复用无独立状态的小片段分组件内与全局两种// 全局 Builder Builder function EmptyView(tip: string) { Column() { Image($r(app.media.empty)) .width(80).height(80) Text(tip).fontColor(#999).margin({ top: 8 }) } } // 组件内 Builder用 this. 调用 Component struct Page { Builder loadingView() { LoadingProgress().width(40).height(40) } build() { Column() { EmptyView(暂无数据) this.loadingView() } } }Builder还支持尾随闭包写法做插槽式组件Component struct Card { BuilderParam content: () void; // 占位插槽 build() { Column() { Text(卡片标题).fontWeight(FontWeight.Bold) this.content(); // 渲染外部传入的内容 } .padding(16) .backgroundColor(#FFF) .borderRadius(12) } } // 使用尾随闭包 Card() { Text(这是卡片内容).fontSize(14) }BuilderParam让组件变成容器类似 Web 的 children slot极大提升复用度。七、Styles 与 Extend样式复用// 组件内 Styles Component struct S { Styles card() { .backgroundColor(#FFF) .borderRadius(12) .padding(16) .shadow({ radius: 8, color: #00000010, offsetY: 2 }) } build() { Column() { }.card() } } // 全局 Extend必须指定组件类型 Extend(Text) function subtitle() { .fontSize(14) .fontColor(#666) } Text(副标题).subtitle()八、组件生命周期自定义组件有一组生命周期回调钩子触发时机aboutToAppear组件即将显示build 前适合初始化数据aboutToDisappear组件即将销毁适合释放资源onPageShow/onPageHide页面显示/隐藏仅 EntryonBackPress用户点击返回Component struct Clock { State now: string ; aboutToAppear(): void { this.now new Date().toLocaleString(); } aboutToDisappear(): void { console.info(时钟组件销毁清理定时器); } build() { Text(this.now) } }九、事件与回调ArkUI 事件通过.onClick、.onChange等链式方法绑定TextInput() .onChange((v) { this.keyword v; }) .onSubmit(() { this.search(); }) Button(长按).gesture( LongPressGesture({ repeat: false }) .onAction(() { console.info(长按触发); }) )手势系统点击、长按、滑动、捏合后面有专门篇章这里先建立事件也是链式属性的认知。十、条件与循环渲染// if/else 条件渲染 if (this.loading) { LoadingProgress() } else if (this.data.length 0) { EmptyView(暂无数据) } else { List() { /* ... */ } } // ForEach 循环渲染 ForEach(this.tabs, (t: string, idx: number) { Text(t).fontColor(idx this.current ? #0A59F7 : #333) }, (t: string) t)注意if/else分支切换会销毁/重建子树频繁切换的场景考虑用透明度等属性替代以保性能。十一、性能优化要点ForEach 必须给稳定 key否则节点错乱、重渲染。大列表用 List 虚拟滚动不要直接 Column 堆几百项。提取自定义组件减少 build 函数体积便于框架复用。避免在 build 里做重计算计算放aboutToAppear或State更新时。用 BuilderParam 做插槽减少包裹层。十二、总结ArkUI 的声明式范式让界面 状态的函数。本文覆盖了内置组件、Image、List 懒加载、自定义组件、Builder/BuilderParam插槽、Styles/Extend样式复用、生命周期与事件绑定。掌握这些你已能用 ArkUI 搭出结构清晰、可复用的界面。但 UI 真正的灵魂是状态如何流动——下一篇我们深入状态管理。