1. 认识基本的组件结构
ArkTS通过装饰器@Component 和@Entry 装饰 struct 关键字声明的数据结构,构成一个自定义组件
自定义组件中提供了一个build函数,开发者需要在函数内以链式调用的方式进行基本的UI描述,UI描述的方法请参考UI描述规范
- srtuct-自定义组件基于struct实现
要想实现一段UI描述,必须使用struct关键字来声明-注意不能有继承关系-组件名不能与系统组件名相同
@Component
struct Index{
}
@CustomDialog
struct Index2{
}
Component修饰符
Component装饰器只能修饰struct关键字声明的结构,被修饰后的struc具备组件的{描述(渲染)能力}的描述
自定义组件就是Conponent修饰了一段struct结构体,里面有一段build函数,里面是写uI的
快速生成自定义组件:comp+回车
- build函数
用于定义组件的UI描述,一个struct结构必须实现build函数
@Component
struct {
build() {
}
}
- build函数是组件(Component)必须提供以实现的一个函数,build函数可以没有内容,如果有的话,必须有且一个容器组件(可以防止子组件的组件)-只有entry里面有限制-component的组件可以放没有子组件的组件
- 常见的容器组件-Flex-Column-Row-List-Grid-Panel
- entry修饰符
entry将自定义组件定义为UI页面的入口,也就是我们原来前端常说的一个页面,最多可以使用entry修饰
一个自定义组件(在一个ets文件中)-如下面的代码是不允许的
entry修饰的组件,最终会被注册,具体文件位置-main/resources/base/profile/main_pages.json
自动注册-新建组件时,采用新建Page的方式
手动注册-新建一个ets文件,自己在main_pages.json中手动添加路径
注意:如果你手动删除了某一个带entry的组件,你需要手动去main_page中去删除该路径,否则编译器会报错
2.组件调用
通过属性方法配置组件属性,以"."链式调用的方式配置组件的样式和其他属性
根据组件构造方法的不同,组件的调用有两种方式
-
有参数
-
无参数
-
Divider().color(Color.White)
-
3.某些组件方法
- 设置主轴对齐
ts
.justifyContent(FlexAlign.Center)
-
给分隔线设置宽度
.strokeWidth(5)//stoke width 笔画宽度
4. 装饰器
装饰器作用:装饰类、结构体等使其拥有新能力
标志:带上@符号的
-
@Entry 入口装饰器
一个页面只能有一个入口
-
@Component 可复用组件
-
数据绑定装饰器 -State
-
State装饰器的变量是组件内部的状态变量、数据改变触发组件所在的build方法刷新UI
举个例子来说,当我们点击某个butto按钮时,触发点击点击事件,如果我们定义普通的变量,而不加@State修饰,当数据改变时,数据改变触发组件所在build方法刷新UI的重新渲染,在ArkUI中统称为状态管理机制。通过状态管理机制可以构建一个动态
下面案例会具体指出
- @Prop - 单项数据传输器
- @Link - 双向数据传输器
- @Watch - 状态变化监听
- @StorageProp(key):这个装饰器可能用于标记一个属性(property),表示这个属性应该被存储在某种形式的存储介质中(如数据库、本地存储等)
- @StorageLink(key):这个装饰器可能用于标记一个方法或属性,表示它与存储介质中的某个数据项或集合有关联。
5.声明式UI - 事件配置
. 事件方法设置组件事件的响应逻辑,以"."链式调用的方式配置系统组件支持的事件
- 匿名函数配置事件方法
使用"()=>{...} ",以确保函数与组件绑定,同时符合ArkTS语法规范
ts
Button("-")
.onClick(() =>{//箭头函数
this.count--
})
- 成员函数配置事件方法
组件内部定义的事件方法
ts
myClickHandler():void {
this.counter += 2;
}
...build() {
Button('add counter')
.onClick(this.myClickHandler.bimd(this))
}
6.案例练习
实现简单计数器(华为实训平台)
ts
@Entry
@Component
struct DrinkWater {
@State count: number = 0
// count:number = 0
build() {
Row() {
Column() {
Text("简易计数器")
//颜色显示方法:对象.属性
.fontColor(Color.Red)
.fontSize('50vp')//如果,因为需要字符串类型加单位需要加双引号
// .fontWeight(FontWeight.Bold)
Divider().color(Color.White)
.strokeWidth(5)
Column(){
Text("喝水次数")
.margin({top:5})
.fontColor(Color.Black)
.fontSize(30)
Row(){
Button("-")
.onClick(() =>{//箭头函数
this.count--
})
.fontSize(30)
Text(""+this.count)
.fontSize(50)
Button("+")
.fontSize(30)
.onClick(() =>{//箭头函数
this.count++
})
Text()
}.justifyContent(FlexAlign.Center)//设置垂直居中
.width('100%')
.height('80%')
// Text("0")
// .fontColor(Color.Blue)
// .fontSize()
}
.margin({top:20})
.width('90%')
.height('20%')
.backgroundColor(Color.White)
.borderColor(Color.Black)
.borderWidth(5)
}
.width('100%')
.height('100%')
.backgroundColor(Color.Blue)
}
}
}
7. 状态管理
3.1.1 状态管理概述
.状态管理: 应用程序运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。通过状态管理机制可以构建一个动态的、有交互的界面
3.1.2 组件级状态管理
被调用的自定义组件是调用者的子组件,调用者则是子组件的父组件。当父子组件之间需要数据同步时,可以使用@Prop和@Link装饰器
-
单向数据传递
- 子组件数据无需传递给父组件,父组件数据传递给子组件
- 单向数据传递装饰器 - @Prop
- @Prop修饰变量:允许组件内部修改@Prop变量,但变量的更改不会通知给父组件
-
双向数据传递
- 父子组件之间数据双向传递
- 双向数据传递装饰器-@Link
- @Link装饰的变量可与父组件的@State变量建立双向数据绑定,任何一方有所修改都会反映给对方
-
@Prop案例练习
ts
@Entry //由@Entry修饰的是入口组件
//一个页面只能有一个Entry
@Component//由@Component修饰的就是自定义组件
struct DrinkWater {
@State count1: number = 0
// count:number = 0
build() {
Row() {
Column() {
Text("简易计数器")
//颜色显示方法:对象.属性
.fontColor(Color.Red)
.fontSize('50vp')//如果,因为需要字符串类型加单位需要加双引号
// .fontWeight(FontWeight.Bold)
Divider().color(Color.White)
.strokeWidth(5)
Column(){
Text("喝水次数")
.margin({top:5})
.fontColor(Color.Black)
.fontSize(30)
Row(){
Button("-")
.onClick(() =>{//箭头函数
this.count1--
})
.fontSize(30)
Text(""+this.count1)
.fontSize(50)
Button("+")
.fontSize(30)
.onClick(() =>{//箭头函数
this.count1++
})
Text()
}.justifyContent(FlexAlign.Center)//设置垂直居中
.width('100%')
.height('80%')
Text("0")
.fontColor(Color.Blue)
.fontSize(20)
}
.margin({top:20})
.width('90%')
.height('20%')
.backgroundColor(Color.White)
.borderColor(Color.Black)
.borderWidth(5)
// sonComp({count2:this.count1})
sonComp({count2:this.count1})
}
.width('100%')
.height('100%')
.backgroundColor(Color.Blue)
}
}
}
//子组件会继承父组件的宽高
@Component //可复用的
struct sonComp{
@Prop count2:number
build() {
Column(){
Text("喝水次数")
.margin({top:5})
.fontColor(Color.Black)
.fontSize(30)
Row(){
Button("-")
.onClick(() =>{//箭头函数
this.count2--
})
.fontSize(30)
Text(this.count2.toString())
.fontSize(50)
Button("+")
.fontSize(30)
.onClick(() =>{//箭头函数
this.count2++
})
}.justifyContent(FlexAlign.Center)//设置垂直居中
.width('100%')
.height('80%')
.backgroundColor(Color.Pink)
}
.margin({top:20})
.width('90%')
.height('20%')
.backgroundColor(Color.White)
.borderColor(Color.Black)
.borderWidth(5)
}
}
效果展示
- @Link案例练习
ts
@Entry //由@Entry修饰的是入口组件
//一个页面只能有一个Entry
@Component//由@Component修饰的就是自定义组件
struct DrinkWater {
@State count1: number = 0
// count:number = 0
build() {
Row() {
Column() {
Text("简易计数器")
//颜色显示方法:对象.属性
.fontColor(Color.Red)
.fontSize('50vp')//如果,因为需要字符串类型加单位需要加双引号
// .fontWeight(FontWeight.Bold)
Divider().color(Color.White)
.strokeWidth(5)
Column(){
Text("喝水次数")
.margin({top:5})
.fontColor(Color.Black)
.fontSize(30)
Row(){
Button("-")
.onClick(() =>{//箭头函数
this.count1--
})
.fontSize(30)
Text(""+this.count1)
.fontSize(50)
Button("+")
.fontSize(30)
.onClick(() =>{//箭头函数
this.count1++
})
Text()
}.justifyContent(FlexAlign.Center)//设置垂直居中
.width('100%')
.height('80%')
Text("0")
.fontColor(Color.Blue)
.fontSize(20)
}
.margin({top:20})
.width('90%')
.height('20%')
.backgroundColor(Color.White)
.borderColor(Color.Black)
.borderWidth(5)
// sonComp({count2:this.count1})
sonComp({count2:this.count1})//会报错,但是不影响使用
//soncomb({count2:$count1})不会报错
}
.width('100%')
.height('100%')
.backgroundColor(Color.Blue)
}
}
}
//子组件会继承父组件的宽高
@Component //可复用的
struct sonComp{
@Link count2:number
build() {
Column(){
Text("喝水次数")
.margin({top:5})
.fontColor(Color.Black)
.fontSize(30)
Row(){
Button("-")
.onClick(() =>{//箭头函数
this.count2--
})
.fontSize(30)
Text(this.count2.toString())
.fontSize(50)
Button("+")
.fontSize(30)
.onClick(() =>{//箭头函数
this.count2++
})
}.justifyContent(FlexAlign.Center)//设置垂直居中
.width('100%')
.height('80%')
}
.margin({top:20})
.width('90%')
.height('20%')
.backgroundColor(Color.White)
.borderColor(Color.Black)
.borderWidth(5)
}
}
效果展示
3.1.3 应用级状态管理
概念:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理
3.1.4 其他状态管理
- @Watch用来监听状态变量的变化,当它修饰的状态变量发生变更时,回调相应的方法
代码演示
ts
@Entry
@Component
struct Notice {
@State sweet:string = "甜度100"
//监测事件
@State @Watch("sweetChange") sweIndex:number = 100
build() {
Column() { //当图片在rawfile文件中,需要佳img.png
Image($r('app.media.img'))//image组件,加入图片路径
.width("70%")
.height("20%")
.margin({top:20})
Text(this.sweet)
.fontSize(50).margin({top:5})
Button("检测甜度")
.onClick(() =>{
this.sweIndex+=10
})
}
.width('100%')
.height('100%')
}
//作为我们的成员方法,跟成员的变量位置一样,在组件内部build组件内部
sweetChange() {
this.sweet = "甜度超标"
}
}
效果展示
代码分析: