HarmonyOS 4.0 应用开发快速入门之 02-组件基础
ArkTS
ArkTS 简介
ArkTS 是 HarmonyOS 的主力应用开发语言。
ArkTS 围绕应用开发在 TypeScript 生态基础上做了进一步扩展,继承了 TypeScript 的所有特性,是 TypeScript 的超集。
JS、TS、ArkTS 的历史:
- JavaScript 由 Mozilla 创建,最初用于解决网页逻辑交互问题,成为 Web 开发基础。
- TypeScript 由 Microsoft 创建,旨在增强 JavaScript,引入类型系统、类型检查等,提高大型应用程序的可维护性。
- React.js 和 Vue.js 等前端框架引入了声明式 UI 和响应式编程的概念,使 Web 应用程序更容易开发和维护。
- ArkTS 建立在 JS 和 TS 的基础之上,扩展了声明式 UI 开发范式和状态管理,提供更简洁和自然的开发方式。
声明式 UI
声明式 UI 是一种编程范式,开发者只需要告诉程序希望界面呈现什么样的结果,而不需要告诉它具体如何去一步步实现这个界面。
声明式 UI 的思想:
- 描述 UI 的呈现结果,而不关心过程。
- 状态驱动视图更新。
组件结构
基础组件结构
ets 文件代码的基本结构:
基础组件的构成:
- ArkTS 通过装饰器 @Component 和 @Entry 装饰 struct 关键字声明的数据结构,构成页面组件。
- 自定义组件中提供了一个 build 函数,开发者需在该函数内以链式调用的方式进行基本的 UI 描述,UI 描述的方法请参考 UI 描述规范。
- 在组件中,UI 描述的 build 方法必须实现,并且里面有且只能有一个根元素。
页面组件
在 DevEco Studio 中,右键 pages 文件夹 → 新建 → Page,可以快速新建一个页面组件。
所有的页面都要在 src/main/resources/base/profile/main_pages.json 中存在配置。
{
"src": [
"pages/Index"
]
}在页面中自定义组件
在页面组件中,可以将通用的部分抽取成一个公共的组件。
示例:在页面组件中定义 Footer 组件
Index 组件(src/main/ets/pages/Index.ets):
// 定义Footer组件
@Component
struct Footer {
build() {
Text('Footer')
}
}
@Entry
@Component
struct Index {
build() {
Column() {
// 在页面中调用组件
Footer()
}
}
}示例效果:
将组件抽取到一个 ets 文件
为了更好地维护组件,自定义组件通常会新建为一个 ets 文件,并放在 ets/components 文件夹下。
示例:将 Footer 组件拆分到单独的 ets 文件
Footer 组件(src/main/ets/components/Footer.ets):
@Preview // 用于在预览模式下预览该组件
@Component
// export default导出组件
export default struct Footer {
build() {
Column() {
Text('Footer')
}
}
}Index 组件(src/main/ets/Index.ets):
// import导入组件
import Footer from './components/Footer.ets'
@Entry
@Component
struct Index {
build() {
Column() {
// 在页面中调用组件
Footer()
}
}
}系统组件
Text 文本组件
Text 文本组件用于显示一段文本。
Text 文本组件的基本用法:
Text(content?: string | Resource)Text 文本组件的基本参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| content | string/Resource | 文本内容 |
Text 文本组件的基本样式属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| textAlign | TextAlign | 文本水平对齐方式,默认值为 TextAlign.Start |
| lineHeight | string/number/Resource | 文本行高 |
示例:Text 组件
Index 组件(src/main/ets/pages/Index.ets):
Text('Hello HarmonyOS')
.fontSize(50) // 字体大小
.fontWeight(FontWeight.Bold) // 字体粗细
.lineHeight(60) // 行高示例效果:
Column 列组件
Column 列组件用于创建沿垂直方向布局的容器。
Column 列组件的基本用法:
Column(value?: {space?: string | number})Column 列组件的基本参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| space | string/number | 纵向布局元素垂直方向间距 |
Column 列组件的基本样式属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| alignItems | HorizontalAlign | 子组件水平方向上的对齐格式,默认值为 HorizontalAlign.Center |
| justifyContent | FlexAlign | 子组件在垂直方向上的对齐格式,默认值为 FlexAlign.Start |
示例:Column 列组件
Index 组件(src/main/ets/pages/Index.ets):
Column() {
Text('Hello HarmonyOS')
.fontSize(22)
}
.width('100%') // 宽度
.alignItems(HorizontalAlign.Start) // 水平居左
.justifyContent(FlexAlign.Start) // 垂直居上示例效果:
Row 行组件
Row 行组件用于创建沿水平方向布局的容器。
Row 行组件的基本用法:
Row(value?:{space?: number | string })Row 行组件的基本参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| space | string/number | 横向布局元素垂直方向间距 |
Row 行组件的基本样式属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| alignItems | VerticalAlign | 子组件在垂直方向上的对齐格式,默认值为 VerticalAlign.Center |
| justifyContent | FlexAlign | 子组件在水平方向上的对齐格式,默认值为 FlexAlign.Start |
示例:Row 组件
Index 组件(src/main/ets/pages/Index.ets):
Row() {
Text('Hello HarmonyOS')
.fontSize(22)
}
.alignItems(VerticalAlign.Top) // 垂直居上
.justifyContent(FlexAlign.Center) // 水平居中
.width('100%')示例效果:
Button 按钮组件
Button 按钮组件用于快速创建不同样式的按钮。
Button 按钮组件的基本用法:
Button(options?: {type?: ButtonType, stateEffect?: boolean})
Button(label?: ResourceStr, options?: { type?: ButtonType, stateEffect?: boolean })Button 按钮组件的基本参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| label | ResourceStr | 按钮的文本内容 |
| options | { type?: ButtonType, stateEffect?: boolean } | 按钮的配置信息 |
| type | ButtonType | 按钮显示样式,默认值为 ButtonType.Capsule |
| stateEffect | boolean | 按钮按下时是否开启按压态显示效果,默认值为 true |
Button 按钮组件的基本样式属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| type | ButtonType | 同上 |
| stateEffect | boolean | 同上 |
Button 按钮组件的基本事件:
| 名称 | 描述 |
|---|---|
| onClick(event: (event?: ClickEvent) => void) | 点击事件 event:按钮点击时触发的方法 |
| stateEffect | 同上 |
示例:Button 按钮组件
Index 组件(src/main/ets/pages/Index.ets):
// 普通按钮
Button('Button')
// 圆形按钮
Button('Button', { type: ButtonType.Circle })
Button('Button')
.type(ButtonType.Circle)
// 按钮点击事件
Button('Button')
.onClick(() => {
console.log('Button click')
})示例效果:
TextInput 单行文本框组件
TextInput 单行文本框组件用于快速创建单行文本输入框。
TextInput 单行文本框组件的基本用法:
TextInput(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextInputController})TextInput 单行文本框组件的基本参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| placeholder | ResourceStr | 输入框的提示文本 |
| text | ResourceStr | 输入框的文本内容 |
TextInput 单行文本框组件的基本样式属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| type | InputType | 输入框类型,默认值为 InputType.Normal |
| maxLength | number | 文本的最大输入字符数 |
TextInput 单行文本框组件的基本事件:
| 名称 | 描述 |
|---|---|
| onChange(callback: (value: string) => void) | 输入内容发生变化时,触发该回调 callback:内容发生变化时触发的方法 value:输入的文本内容 |
示例:TextInput 单行文本框组件
Index 组件(src/main/ets/pages/Index.ets):
// 普通的单行文本框
TextInput({placeholder: '请输入手机号'})
// 密码类型的单行文本框
TextInput()
.type(InputType.Password)
// 单行文本框内容变化回调事件
TextInput()
.onChange((value) => {
console.log('new value is ' + value)
})示例效果:
Image 图片组件
Image 图片组件常用于在应用中显示图片。
Image 图片组件的基本用法:
Image(src: string | PixelMap | Resource)Image 图片组件的基本参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| src | string/PixelMap/Resource | 图片的数据源 |
Image 图片组件的基本样式属性:
| 名称 | 类型 | 描述 |
|---|---|---|
| objectFit | ImageFit | 图片的填充效果,默认值为 ImageFit.Cover |
| fillColor | ResourceColor | 设置填充颜色,仅对 svg 图源生效 |
示例:Image 图片组件
Index 组件(src/main/ets/pages/Index.ets):
Image($r('app.media.avatar'))
.width(50)
Image($r('app.media.ic_public_heart'))
.fillColor('#c3c44c5')
.width(50)示例效果:
组件状态基础
组件变量
组件变量不具备驱动 UI 更新能力。
示例:组件变量
Index 组件(src/main/ets/pages/Index.ets):
@Entry
@Component
struct Index {
// 组件变量,数据改变,界面不会自动变化
count = 0
build() {
Column(){
Text(this.count.toString())
Button('++')
.onClick(() => {
this.count++
})
}
}
}示例效果:
状态变量
参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-state-0000001474017162-V2
状态变量指驱动 UI 更新的数据,加上 @State 装饰器即可。
示例:状态变量
Index 组件(src/main/ets/pages/Index.ets):
@Entry
@Component
struct Index {
// 组件变量,数据改变,界面自动变化
@State
count: number = 0
build() {
Column(){
Text(this.count.toString())
Button('++')
.onClick(() => {
this.count++
})
}
}
} 示例效果:
双向数据绑定
在 TextInput 组件中实现双向数据绑定:
- 设置 TextInput 组件的 text 属性为 TextInput 绑定数据。
- 通过 onChange 事件将状态变量与文本实时绑定,避免组件刷新时 TextArea 中的文本内容异常。
示例:TextInput 双向数据绑定
Index 组件(src/main/ets/pages/Index.ets):
@Entry
@Component
struct Index {
@State phone:string = ''
build() {
Row() {
Column({space: 10}) {
Row() {
// TextInput双向数据绑定:
// 1、通过onChange事件将状态变量与文本实时绑定
// 2、通过text属性设置输入框的文本内容
TextInput({text: this.phone, placeholder: '请输入手机号'})
.onChange((value) => {this.phone = value})
}
Row() {
Button('重置')
.backgroundColor('#CCCCCC')
.margin(10)
.onClick(() => {
this.phone = ''
})
Button('登录')
.margin(10)
.onClick(() => {
console.log('success')
})
}
Row() {
Text('输入的手机号:' + this.phone)
}
}
.width('100%')
}
.height("100%")
.padding(20)
.alignItems(VerticalAlign.Top)
}
}示例效果: