前言
1. 常用容器组件
- Column:沿垂直方向布局的容器组件。
- Row:沿水平方向布局的容器组件。
- Stack:堆叠容器组件,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
- Flex:以弹性方式布局子组件的容器组件。
说明:
1.Flex组件主轴默认不设置时撑满父容器,Column、Row组件主轴不设置时默认是跟随子节点大小。
2.Flex组件在渲染时存在二次布局过程,因此在对性能有严格要求的场景下建议使用Column、Row代替。
2. 列表组件
- List:列表包含一系列相同宽度的列表项,适合连续、多行呈现同类数据,例如图片和文本。
- ListItem:用来展示具体列表项,必须配合List来使用。
- ListItemGroup:用来展示分组列表项的组件,必须配合List组件来使用。
3. 宫格组件
- Grid:网格容器组件,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。
- GridItem:网格容器中单项内容容器。
4. 文本与输入组件
- Text:显示一段文本的组件。
- Span:作为Text组件的子组件,用于显示行内文本片段的组件。
- TextInput:单行文本输入框组件。
- TextArea:多行文本输入框组件,当输入的文本内容超过组件宽度时会自动换行显示。
- RichText:富文本组件,解析并显示HTML格式文本。
5. 空白与分隔组件
- Blank:空白填充组件,在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。仅当父组件为Row/Column时生效。
- Divider:分隔器组件,分隔不同内容块/内容元素。
一、构建第一个页面
// Index.ets
// 装饰器(带@修饰)。可以用来装饰类结构、方法、变量,如:@Entry、@Component、@State等
@Entry // @Entry 标记当前组件是入口组件,即这个组件代表一个页面可以被独立访问显示。没有这个装饰器的组件就是普通组件,不能单独显示,只能被其它页面引用,做页面元素的封装(相当于子视图)
@Component // @Component 标记这个结构体是一个自定义组件
// 这个结构体在ArkTS中称为,自定义组件:可复用的UI单元
struct Index {
// @State 用来标记一个变量是状态变量,值变化时会触发UI刷新
// 声明式UI特点:状态数据变化驱动页面UI自动刷新
@State message: string = 'Hello World'
// 构建组件内容,UI描述:其内部以声明式方式描述UI结构
build() {
// 内置组件:ArkUI提供的组件
// 容器组件:用来完成页面布局,例如:Row、Column
// 基础组件:自带样式和功能的页面元素,例如:Text
Row() {
Column() {
Text(this.message)
// 属性方法:设置组件的UI样式
.fontSize(50)
.fontWeight(FontWeight.Bold)
// 事件方法:设置组件的事件回调(传一个回调函数)
.onClick(() => {
// ...处理事件
this.message = 'Hello ArkTS!'
})
}
.width('100%')
}
.height('100%')
}
}
二、Image组件
- 组件使用
// 需要配置网络访问权限,才能请求网络资源
Image('https://gbres.dfcfw.com/Files/picture/20240107/A647B2359640C398075289DFB100768F_w707h782.jpg')
// 指定图片宽度,高度会自动按图片宽高比自动缩放
.width(300) // 数字格式,如:300vp,会有一个默认单位vp(虚拟像素:不是真正屏幕像素,会根据设备像素密度进行换算,确保在不同设备上视觉大小一样)
//.width('100%') // 字符串格式,如:'100%',百分比模式(根据设备大小自动伸缩)
- 访问控制权限申请
在module.json5文件中添加如下内容:
{
"module": {
// 配置权限(系统权限、用户权限)
"requestPermissions": [
{
// 配置网络权限(属于系统权限,只需要配置name即可)
"name": "ohos.permission.INTERNET"
}
],
... ...
}
三、Text组件
注意:base目录是默认目录,在读取本地资源文件String时,会优先匹配限定词目录(国际化),匹配不到再去base目录。
四、TextInput组件
// 常见数据类型转换
let text = '200'
let num = parseInt(text) // 字符串 转 数字
let string = num.toFixed(0) // 数字 转 字符串(保留0位小数)
五、Button组件
六、Slider组件
七、页面布局组件
- <Column>容器(列容器,纵向布局,从上到下排列)
- <Row>容器(行容器,横向布局,从左到右排列)
-
布局示例
-
justifyContent:子元素在主轴方向的对齐方式
-
alignItems:子元素在交叉轴方向的对齐方式
-
案例
@Entry
@Component
struct ImagePage {
@State imageWidth: number = 150
build() {
Column() {
Row() {
Image('https://gbres.dfcfw.com/Files/picture/20240107/A647B2359640C398075289DFB100768F_w707h782.jpg')
.width(this.imageWidth)
.interpolation(ImageInterpolation.High)
}
.width('100%')
.height(300)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.backgroundColor('#f1f1f1')
Row() {
Text('图片宽度:')
.fontSize(20)
TextInput({ placeholder: '请输入图片宽度', text: this.imageWidth.toFixed(0) })
.type(InputType.Number)
.onChange(value => {
this.imageWidth = parseInt(value)
})
.backgroundColor('#f1f1f1')
.fontSize(20)
.width(200)
}
.width('100%')
.margin({top: 30})
.padding({left: 15, right: 15})
.justifyContent(FlexAlign.SpaceBetween)
.backgroundColor('#f1f1f1')
// 分割线
Divider()
Row() {
Button('缩小')
.width(88)
.fontSize(20)
.onClick(value => {
if (this.imageWidth >= 100) {
this.imageWidth -= 20
}
})
Button('放大')
.width(80)
.fontSize(20)
.onClick(value => {
if (this.imageWidth <= 300) {
this.imageWidth += 20
}
})
}
.width('100%')
.margin({top: 30})
.justifyContent(FlexAlign.SpaceEvenly)
.backgroundColor('#f1f1f1')
Row() {
Slider({
min: 100,
max: 300,
value: this.imageWidth,
step: 20
})
.blockColor('#bbccdd')
.trackThickness(8)
.showTips(true)
.showSteps(true)
.onChange(value => {
this.imageWidth = value
})
}
.margin({top: 30})
.backgroundColor('#f1f1f1')
}
.width('100%')
.height('100%')
.padding(20)
}
}
- 渲染控制(列表渲染、条件渲染)
- 提示:其中的
index?
、keyGenerator?
是可选参数,可以不写
八、List复杂容器
九、自定义组件
-
@Component
自定义组件:是将代码封装成组件,通过导出导入方式进行使用。方便代码复用,使代码更加简洁。
// 自定义一个标题栏组件
@Component
// 导出组件,方便其它文件导入使用
export struct Header {
// ResourceStr:是 string | Resource的别名。表示既可以直接传字符串,又可以传本地资源字符串(string.json中的内容)
private title: ResourceStr = ''
build() {
Row({space: 8}) {
Image($r('app.media.icon'))
.width(30)
Text(this.title)
.fontSize(28)
.fontWeight(FontWeight.Bold)
Blank() // 空白组件,相当于弹簧效果,撑满剩余空间,将图标挤到最右边去
Image($r('app.media.icon'))
.width(30)
}
.width('100%')
}
}
// 在其它文件使用的时候:
// 1.先导入组件,如:import {Header} from '../components/Header'
// 2.直接使用组件,如:Header({title: '商品列表'})
@Builder
自定义构建函数:是将代码封装成函数,通过函数调用进行使用。方便代码复用,使代码更加简洁。
注意:
1》定义在组件外部的函数是全局函数,因为函数没有在class/struct中,所以定义的时候需要function关键字,使用的时候直接调用即可。
函数定义格式:@Builder function ItemCard(item: Item) { ... }
函数调用格式:ItemCard(item)
2》定义在组件内部的函数是局部函数,定义的时候不需要function关键字,使用的时候需要通过"this.函数名"进行调用
函数定义格式:@Builder ItemCard2(item: Item) { ... }
函数调用格式:this.ItemCard2(item)
@Styles
扩展组件公共样式:和上面的自定义构建函数一样,将公共样式/属性方法封装成函数,通过函数调用进行使用。
// 扩展组件通用属性(适用于所有组件)
// 调用和使用系统的属性方法一样,如:.fillScreen()
@Styles function fillScreen() {
// 注意点:这里面写的属性必须是所有组件的通用属性
.width('100%')
.height('100%')
.backgroundColor('#f1f1f1')
.padding(20)
// 如:字体大小属性不是所有组件的通用属性,写会报错;为了解决这个问题,可以使用 @Extend 来扩展指定组件的样式
//.fontSize(18)
}
-
@Extend
扩展特定组件样式
// 扩展组件特有属性(仅可定义在全局)
@Extend(Text) function titleStyle(fontSize: number = 20) {
.fontSize(fontSize)
.fontColor('#333')
}