【HarmonyOS NEXT】Grid组件怎么同步父组件和子组件

文章讲述了在Vue应用中,如何处理子组件的@ObjectLink装饰变量的变化能同步到父组件的列表,以及如何通过封装子组件和使用@Observed来实现双向数据绑定和列表更新的问题及解决方案。
摘要由CSDN通过智能技术生成

【关键字】

Grid组件 / 父组件 / 子组件 / @ObjectLink

【问题描述】

问题一:

点击子组件后,子组件点击事件有响应,但是父组件list没有变化,子组件的二级属性变化怎么同步到父组件的list?

问题二:

子组件中使用@ObjectLink装饰的变量属性变化时,父组件list能同步这个变化并刷新父组件UI。因为需要根据子组件变量的状态显示父组件list的内容,一旦发生变化,list就去掉这些变化的数据,父组件不显示这部分子组件。请问需要用什么其他的方案来实现?

代码示例:

【数据模型】

@Observed
export class BusinessInfo {
icon: string //图片链接
menuName?: string//菜单名称
selected?:boolean//是否选中
}

【子组件】

export default struct CourseItem {
@ObjectLink item: BusinessInfo

build() {
Column() {
Image(this.item.icon)
.width(24)
.height(24)
Text(this.item.menuName)
}
.onClick(()=>{
this.item.selected = true
})
}
}

【父组件】

@State topList: BusinessInfo[] = []
Grid() {
ForEach(this.getSelectedMenuItems(this.topList), (titleInfo: BusinessInfo, index?: number) => {
ForEach([titleInfo], (course: BusinessInfo) => {
GridItem() {
CourseItem({ item: course })
.width(33.33%)
}
}, (CourseItem: BusinessInfo) => `${CourseItem.menu_id}`)
}, (parentItem: BusinessInfo) => `${parentItem.menu_id}`)
}
//过滤选中的子组件
getSelectedMenuItems(list: BusinessInfo[] | undefined): BusinessInfo[] {
if (list == undefined) {
return []
}
let isSelected: boolean = false
let newList: BusinessInfo[] = []
for (let index = 0; index < list.length; index++) {
const element:BusinessInfo = list[index] as BusinessInfo
if (element.selected == true) {
isSelected = true
} else {
newList.push(element)
}
}
if (isSelected) {
return newList
} else {
return list
}
}

【解决方案】

问题一:

子组件中使用@ObjectLink装饰的变量可以观察到属性变化,所以子组件页面会刷新,但是主组件虽然用@state装饰了topList,但是topList中某个值变化不会被观察到。其实topList的值已经通过子组件刷新了。

如果主组件还有其他信息要根据list的内容展示,建议也封装成子组件并且通过@ObjectLink修饰。

样例如下:

let NextID: number = 1;

@Observed
class ClassA {
public id: number;
public c: number;

constructor(c: number) {
this.id = NextID++;
this.c = c;
}
}

@Component
struct ViewA {
// 子组件ViewA的@ObjectLink的类型是ClassA
@ObjectLink a: ClassA;
label: string = 'ViewA1';

build() {
Row() {
Button(`ViewA [${this.label}] this.a.c = ${this.a ? this.a.c : "undefined"}`)
.onClick(() => {
this.a.c += 1;
})
}
}
}

@Component
struct ViewC {
// 子组件ViewA的@ObjectLink的类型是ClassA
@ObjectLink a: ClassA;
label: string = 'ViewB1';

build() {
Row() {
Text(this.a.c.toString())
}
}
}

@Entry
@Component
struct ViewB {
// ViewB中有@State装饰的ClassA[]
@State arrA: ClassA[] = [new ClassA(0), new ClassA(0)];
build() {
Column() {
ForEach(this.arrA,
(item: ClassA) => {
ViewA({ label: `#${item.id}`, a: item })
},
(item: ClassA): string => item.id.toString()
)
// 使用@State装饰的数组的数组项初始化@ObjectLink,其中数组项是被@Observed装饰的ClassA的实例
ViewA({ label: `ViewA this.arrA[first]`, a: this.arrA[0] })
ViewA({ label: `ViewA this.arrA[last]`, a: this.arrA[this.arrA.length-1] })
//封装子组件感知对象属性变化
ViewC({a:this.arrA[0]})
//@state装饰的数组内容变化不会被观察到
Text(this.arrA[0].c.toString())
}
}
}

问题二:

可以把list也封装到子组件中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值