1、组件状态共享
State是当前组件的状态, 用State修饰的数据变化会驱动UI的更新(只有第一层)
父传子的时候,子组件定义变量的时候,如果没有任何的修饰符,那么该值只会在第一次渲染时生效
1.1、状态共享-父子单向
@Prop 装饰的变量可以和父组件建立单向的同步关系。@Prop 装饰的变量是可变的,但是变化不会同步回其父组件。-Prop是用在子组件中的
Prop只能修饰string number boolean类型的数据- (Next全部都支持了各种类型)
- 完成父 - 子的单向同步
@Entry
@Component
struct PropCase {
@State message: string = 'Hello World'
@State num:number = 0
build() {
Row() {
Column({space:20}) {
Text(this.num.toString()).fontSize(50).fontWeight(FontWeight.Bold)
.onClick(() => {
this.num++
})
Divider()
.strokeWidth(6)
Child({num:this.num})
}
.width('100%')
}
.height('100%')
}
}
@Component
struct Child {
@Prop
num:number
build() {
Text(this.num.toString()).fontSize(40).fontColor(Color.Red)
.onClick(() => {
this.num++
})
}
}
我们发现使用Prop修饰的状态,只会在当前子组件生效,不会传导到父组件,所以它属于一种单向传递
- 支持类型 string、number、boolean、enum 类型- 下个版本支持的类型更多
- 子组件可修改 Prop 数据值,但不同步到父组件,父组件更新后覆盖子组件 Prop 数据
- 子组件可以初始化默认值,注意:目前编译器会提示错误,请忽略,下个版本将修复
1.2、状态共享-父子双向
- Prop修饰符- 父组件数据更新-让子组件更新- 子组件更新-父组件不为所动
Prop是单向的,而Link修饰符则是双向的数据传递,只要使用Link修饰了传递过来的数据,这个时候就是双向同步了
注意点:在父组件传入Link属性时,需要使用$来修饰该变量,去掉this
Child({num:$num})
@Link num:number
// 子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定
需要注意的是,Link修饰的变量类型变得更为宽泛,支持string、number、boolean、enum Object Class以及这些类型对应的数组
小结:
调试技巧:
- console.log('vc-----:'+'')加前缀
- 可以使用弹出信息的方式-或者显示文本到页面的形式
// AlertDialog.show({message:this.commentStr}) // alert弹窗
Text(JSON.stringfiy())
ArkTS所有的响应式更新都只能监听到我们的第一层数据
Link修饰的数据必须得是最外层的 State数据
@Entry
@Component
struct LinkCase {
@State message: string = 'Hello World'
@State
list:FoodClass[] = [{
order_id: 1,
food_name: '鱼香肉丝',
food_price: 18.8,
food_count: 1
},{
order_id: 2,
food_name: '粗溜丸子',
food_price: 26,
food_count: 2
},{
order_id: 3,
food_name: '杂粮煎饼',
food_price: 12,
food_count: 1
}]
build() {
Row() {
Column({space:20}) {
ForEach(this.list, (item:FoodClass)=>{
Row() {
Text(item.food_name).TextStyle()
Text(item.food_price.toFixed(2)).TextStyle()
Text(item.food_count.toString()).TextStyle()
}
.height(40)
.width('100%')
})
BottonCard({myList:$list}) // 记得传过去的数据要被state修饰
// Link修饰的数据必须得是最外层的 State数据,如果没有被state修饰,后续ObjectLink 和Observerd会解决这个问题
}
.width('100%')
}
.height('100%')
}
}
@Extend(Text)
function TextStyle() {
.layoutWeight(1).textAlign(TextAlign.Center).fontSize(20)
}
// 食品类
class FoodClass {
order_id: number = 0
food_name: string = ""
food_price: number = 0
food_count: number = 0
}
@Component
struct BottonCard {
@Link
myList:FoodClass[]
build() {
Button('更改菜品的数量')
.onClick(() => {
// map循环数组返回新数组,map中item代表数组中的元素,map会将其中的item组成一个新的数组
this.myList = this.myList.map(item => {
item.food_count++
return item
})
})
}
}
1.2、状态共享-后代组件
如果我们的组件层级特别多,ArkTS支持跨组件传递状态数据来实现双向同步@Provide和 @Consume
变量包括Object、class、string、number、boolean、enum 类型均支持@Provide和 @Consume
例子:假设我们有三层组件,Index-Child-Grand, Index的数据不想经过Child而直接给到Grand可以使用该修饰器
1.2.1、通过相同的变量名绑定
@Entry
@Component
struct ProvideCase {
@Provide money:number = 1000 // Provide跨组件提供数据,实现双向绑定,爷爷提供数据
build() {
Row() {
Column({space:20}) {
Text(`爷爷的钱:${this.money.toString()}`).fontSize(30)
Divider().strokeWidth(3).color(Color.Red)
Father()
}
.width('100%')
}
.height('100%')
}
}
@Component
struct Father {
@Consume money:number
build() {
Column() {
Text('父亲组件').fontSize(30)
.onClick(() => {
this.money += 2
})
Divider().strokeWidth(3).color(Color.Green)
GreateSon()
}
}
}
@Component
struct GreateSon {
@Consume
money:number // Consume跨组件接收数据,实现双向绑定
build() {
Text(`接收到爷爷的钱:${this.money.toString()}`)
.fontSize(20)
.onClick(() => {
this.money -= 10
})
}
}
注意: 在不指定Provide名称的情况下,你需要使用相同的名字来定义和接收数据
1.2.2、通过相同的变量别名绑定
@Provide('key') 和 @Consume('key') key需要保持一致
@Provide('aa') money:number = 1000 // Provide跨组件提供数据,实现双向绑定,爷爷提供数据
@Consume('aa') mon:number // Consume跨组件接收数据,实现双向绑定,Consume的状态变量不需要初始值
ArkTS所有内容都不支持深层数据(包过深层组件)更新 UI渲染
网友评论