[HarmonyOSNext鸿蒙开发]1.ArkTS声明式开发:UI范式基本语法
[HarmonyOSNext鸿蒙开发]1.ArkTS声明式开发:UI范式基本语法
-
- @[TOC]([HarmonyOSNext鸿蒙开发]1.ArkTS声明式开发:UI范式基本语法)
- 一、ArkTS的基本组成
-
- (1)核心概念(像贴标签一样控制组件)
- (2)基础工具包(现成的积木块)
- (3)高效开发技巧(进阶工具箱)
- (4)常见误区提醒及类比理解
- 二、声明式UI描述( 给组件\"搭积木\"的入门指南)
-
- (1)🧱创建组件(像拼乐高一样简单)
- (2)🎨配置属性(给组件穿衣服)
- (3)🕹️配置事件(给按钮装开关)
- (4)🎁 配置子组件(俄罗斯套娃)
- (5)💡避坑指南
- 三、🧩自定义组件的通俗指南
-
- (1)什么是自定义组件?
- (2)为什么需要自定义组件?
- (3)快速入门案例
- (4)🛠️ 组件建造说明书
-
- 组件结构三要素
- 装饰器的作用
- 构建规则(易错点)
- (5)🎨 样式与交互技巧
-
- 链式调用设置样式
- 组件样式继承的坑
- (6)⚠️ 常见问题急救包
- (7)🌰 实战案例:计数器组件
- 🚀 进阶技巧
- @[TOC]([HarmonyOSNext鸿蒙开发]1.ArkTS声明式开发:UI范式基本语法)
- 一、ArkTS的基本组成
-
- (1)核心概念(像贴标签一样控制组件)
- (2)基础工具包(现成的积木块)
- (3)高效开发技巧(进阶工具箱)
- (4)常见误区提醒及类比理解
- 二、声明式UI描述( 给组件\"搭积木\"的入门指南)
-
- (1)🧱创建组件(像拼乐高一样简单)
- (2)🎨配置属性(给组件穿衣服)
- (3)🕹️配置事件(给按钮装开关)
- (4)🎁 配置子组件(俄罗斯套娃)
- (5)💡避坑指南
- 三、🧩自定义组件的通俗指南
-
- (1)什么是自定义组件?
- (2)为什么需要自定义组件?
- (3)快速入门案例
- (4)🛠️ 组件建造说明书
-
- 组件结构三要素
- 装饰器的作用
- 构建规则(易错点)
- (5)🎨 样式与交互技巧
-
- 链式调用设置样式
- 组件样式继承的坑
- (6)⚠️ 常见问题急救包
- (7)🌰 实战案例:计数器组件
- 🚀 进阶技巧
一、ArkTS的基本组成
(1)核心概念(像贴标签一样控制组件)
-
装饰器(给代码贴魔法标签)
• @Component:相当于给代码块贴个“可复用组件”标签。比如你写了个按钮样式,贴上这个标签后,整个程序都能重复使用这个按钮。• @Entry:相当于“主入口”标签,告诉系统:“这个组件是App启动时第一个显示的界面”。
• @State:相当于“自动刷新”标签。比如你在购物车数字上贴了这个标签,当数量变化时,界面会自动更新显示最新数值。
-
UI描述(像写菜谱一样写界面)
用简单直白的代码描述界面结构,比如:build() { Column() { // 竖着排列 Text(\"你好!\").fontSize(20) // 文字 Button(\"点击我\").onClick(() => { 操作代码 }) // 按钮 }}
就像写菜谱说“先放文字,再放按钮”一样直观。
(2)基础工具包(现成的积木块)
-
系统组件(开箱即用的积木)
• 基础积木:文字(Text)、图片(Image)、按钮(Button)• 排列工具:
Column(竖排:像叠汉堡) Row(横排:像排队) Stack(叠放:像贴纸一样层层叠加)RelativeContainer(相对布局:支持容器内部的子元素设置相对位置关系,适用于处理界面复杂的场景,对多个子元素进行对齐和排列。子元素可以指定兄弟元素或父容器作为锚点,基于锚点进行相对位置布局。)
-
属性链式调用(像串珠子一样设置样式)
连续设置多个属性:Text(\"标题\") .fontSize(24) // 字号24 .fontColor(\"#FF0000\") // 红色 .margin({top:10}) // 上方留10像素空白
就像给文字戴项链,一颗接一颗地加装饰。
-
事件绑定(给按钮装开关)
给组件添加交互功能:Button(\"提交\") .onClick(() => { 提交数据 }) // 点击事件 .onLongPress(() => { 弹出菜单 }) // 长按事件
相当于给按钮装了两个触发器:短按和长按分别触发不同操作。
(3)高效开发技巧(进阶工具箱)
-
@Builder(打造自己的积木模具)
把常用的界面片段打包成模板:@Builderfunction RedButton(text:string) { Button(text).backgroundColor(\"#FF0000\")}// 使用时直接调用RedButton(\"危险操作\")
相当于做了一个红色按钮的模具,随用随取。
-
@Styles/@Extend(批量改装修饰)
• 统一风格:给所有标题设置统一样式,类似于CSS中的类样式@Styles function titleStyle() { .fontSize(20) .fontColor(\"#333\")}Text(\"标题1\").titleStyle()
• 扩展组件:给系统按钮添加圆角
@Extend(Button)function roundButton() { .borderRadius(8)}
-
状态样式(智能变装术)
根据组件状态自动切换样式:Button(\"登录\") .stateStyles({ normal: { backgroundColor: \"#EEE\" }, // 默认灰色 pressed: { backgroundColor: \"#CCC\" } // 按下变深灰 })
就像按钮被按下时会“变色回应”你的操作。
(4)常见误区提醒及类比理解
- 装饰器顺序:@Entry必须放在最外层,像信封的收件人地址要写在最上面
- 状态管理:只有被@State标记的变量变化才会触发界面刷新,普通变量修改不会更新显示
- 链式调用:属性设置顺序有时会影响效果(比如先设宽度再设边距可能导致布局错位)
类比理解:
开发界面就像装修房子:
- 装饰器是各种功能标签(如“承重墙”“可拆卸隔断”)
- 系统组件是现成的家具(桌子、椅子)
- @Builder是自己设计的定制家具图纸
- 状态样式是智能家居系统(天黑自动开灯)
二、声明式UI描述( 给组件\"搭积木\"的入门指南)
(1)🧱创建组件(像拼乐高一样简单)
两种组装方式:
-
无参数组件(空手组装)
Divider() // 直接写组件名加空括号,就像拼一根直线
适合不需要额外参数的组件,比如分割线、空白间隔
-
有参数组件(带说明书组装)
// 图片必须带地址参数Image(\'https://example.com/cat.jpg\') // 相当于给图片框塞照片// 文字可以不带内容(显示空文本)Text() // 相当于一个隐形的文字占位符
参数小技巧:
- 可以插入变量或算式:
Image(this.userAvatar) // 使用变量里的图片地址Text(`剩余次数:${5 - this.count}`) // 显示动态计算结果
(2)🎨配置属性(给组件穿衣服)
连续点选设置法:
Text(\'你好世界\') .fontSize(20) // 文字大小 .fontColor(\'#FF0000\') // 文字颜色 .margin({top:10}) // 上方留10像素空白
就像给洋娃娃穿衣服:先穿裙子,再戴帽子,最后穿鞋子
颜色/样式快捷选项:
Text(\'特别提示\') .fontColor(Color.Red) // 使用预定义红色 .fontWeight(FontWeight.Bold) // 直接选\"加粗\"模式
(3)🕹️配置事件(给按钮装开关)
箭头函数用法:
Button(\'点我抽奖\') .onClick(() => { this.luckyNumber = Math.random() // 点击后生成随机数 })
相当于给按钮装了个\"按下就执行\"的魔法开关,箭头函数内部的this是词法作用域,由上下文确定。匿名函数可能会有this指向不明确问题,在ArkTS中不允许使用。
错误用法提醒:
// ❌ 不要用普通函数Button(\'错误示例\') .onClick(function() { // 这里的this会指向错误的地方! })// ✅ 正确用箭头函数Button(\'正确示例\') .onClick(() => { // 箭头函数自动绑定正确上下文 })
(4)🎁 配置子组件(俄罗斯套娃)
容器组件用法:
Column() { // 创建一个垂直排列的容器 Text(\'标题\').fontSize(24) // 第一个子组件 Divider() // 中间加分割线 Image(\'logo.png\').width(100) // 最后放图片}
像往抽屉里放东西:先放书本,再放文具,最后放零食
多层嵌套示例:
Column() { Row() { // 横向排列容器 Image(\'头像.jpg\').width(50) Text(\'张三\').fontSize(16) } Grid() { // 网格布局 Image(\'产品1.jpg\') Image(\'产品2.jpg\') Image(\'产品3.jpg\') }}
(5)💡避坑指南
-
组件创建不用new
// ✅ 正确Text(\'你好\')// ❌ 错误new Text(\'你好\')
-
样式设置顺序不影响(大部分情况)
// 这两种写法效果相同Text().fontSize(20).color(\'red\')Text().color(\'red\').fontSize(20)
-
容器组件必须包含内容
// ✅ 正确用法Column() { Text(\'内容\')}// ❌ 空容器会报错Column()
类比理解:
开发界面就像玩装修游戏:
- 组件是各种家具(按钮=台灯,图片=挂画)
- 属性是家具的皮肤(颜色/尺寸/位置)
- 事件是家具的互动功能(点击台灯会亮)
- 容器是房间布局(书架=垂直排列,电视柜=水平排列)
三、🧩自定义组件的通俗指南
(1)什么是自定义组件?
就像搭乐高积木,系统组件是现成的积木块,而自定义组件是开发者自己设计的特殊积木。它能组合多个积木、重复使用,还能根据数据变化自动更新外观。
(2)为什么需要自定义组件?
- 代码复用:像写好的菜谱,重复使用不重写代码
- 逻辑分离:把界面和数据处理分开,像把食材和烹饪步骤分开
- 维护方便:改一个地方,所有用到的地方自动更新
(3)快速入门案例
// 定义一个会变色的问候组件@Component struct HelloComponent { @State message: string = \'Hello!\'; // 会变的数据 build() { Row() { Text(this.message) .onClick(() => { this.message = \'你戳我干嘛~\'; // 点击后文字变化 }) } }}// 在页面中使用@Entry@Componentstruct MainPage { build() { Column() { HelloComponent() // 使用自定义组件 HelloComponent({ message: \'你好呀!\' }) // 传入不同参数 } }}
(4)🛠️ 组件建造说明书
组件结构三要素
@Component // 🏷️ 组件身份证struct MyComponent { // 🏗️ 组件骨架 build() { /* UI描述 */ } // 🎨 绘制方法}
装饰器的作用
@State
@State count = 0
@Entry
@Entry struct HomePage
@Reusable
@Reusable struct Item
构建规则(易错点)
-
根节点要求:
@Entry @Componentstruct MyPage { build() { // ✅ 正确:容器组件作为根节点 Column() { Text(\'Hello\') } // ❌ 错误:ForEach不能当根节点 // ForEach([1,2,3], ...) }}
-
禁止操作:
build() { // ❌ 不能声明变量 // let num = 1 // ❌ 不能直接改状态 // this.count++ // ✅ 正确方式:通过事件修改 Button(\'+1\').onClick(() => this.count++)}
(5)🎨 样式与交互技巧
链式调用设置样式
Text(\'艺术字\') .fontSize(24) // 字号 .fontColor(\'#FF69B4\') // 粉色 .margin({top:20}) // 上边距
组件样式继承的坑
// 子组件@Componentstruct MyButton { build() { Button(\'按钮\') }}// 父组件使用时MyButton() .backgroundColor(\'red\') // ❌ 这个红色会加在\"隐形容器\"上
(实际效果:按钮外围会有红色背景,而不是按钮本身)
(6)⚠️ 常见问题急救包
-
为什么点击没反应?
- 检查是否漏写
@State
装饰器 - 确认事件绑定用了箭头函数:
.onClick(() => {})
- 检查是否漏写
-
组件显示空白?
- 检查
build()
是否有根节点 - 确认导出了组件:
export struct MyComponent
- 检查
-
样式不生效?
- 尝试用
!important
强制样式:.width(100).width!(\'80%\')
- 尝试用
(7)🌰 实战案例:计数器组件
@Componentexport struct MyCounter { @State num: number = 0 build() { Row() { Button(\'-\').onClick(() => this.num--) Text(`${this.num}`).margin(10) Button(\'+\').onClick(() => this.num++) } }}@Entry@Componentstruct Index { build() { RelativeContainer() { Column() { Text(\'商品数量:\') MyCounter() // 复用计数器 MyCounter({ num: 5 }) // 初始值5 } } .height(\'100%\') .width(\'100%\') }}
Tip:这个组件可以用于购物车、投票等需要增减操作的场景
🚀 进阶技巧
-
组件冻结(API11+):
@Component({ freezeWhenInactive: true }) // 离开屏幕时冻结组件struct LazyComponent {}
-
跨页面传参:
@Entry({ routeName: \'detail\', storage: myStorage })@Componentstruct DetailPage {}
学习路线建议:从简单组件开始 → 掌握状态管理 → 尝试复杂布局 → 优化组件性能