赞
踩
上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。
@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
被@Observed装饰的类,可以被观察到属性的变化;
子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
@Observed用于嵌套类场景中,观察对象类属性变化,要配合自定义组件使用,如果要做数据双/单向同步,需要搭配@ObjectLink或者@Prop使用。
使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
@Observed类装饰 | 说明 |
---|---|
装饰器参 | 无 |
类装饰器 | 装饰class。需要放在class的定义前,使用new创建类对象。 |
@ObjectLink变量装饰器 | 说明 |
---|---|
装饰器参数 | 无 |
允许装饰的变量类型 | 必须为被@Observed装饰的class实例,必须指定类型。 不支持简单类型,可以使用@Prop。 支持继承Date、Array的class实例,API11及以上支持继承Map、Set的class实例。 @ObjectLink的属性是可以改变的,但是变量的分配是不允许的,也就是说这个装饰器装饰变量是只读的,不能被改变。 |
被装饰变量的初始值 | 不允许。 |
组件提供勾选框样式、状态按钮样式及开关样式。
仅当ToggleType为Button时可包含子组件。
Toggle(options: { type: ToggleType, isOn?: boolean })
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
type | ToggleType | 是 | 开关的样式。 默认值:ToggleType.Switch。 |
isOn | boolean | 否 | 开关是否打开,true:打开,false:关闭。 默认值:false 从API version 10开始,该参数支持$$双向绑定变量。 |
名称 | 描述 |
---|---|
Checkbox | 提供单选框样式。 |
Button | 提供状态按钮样式,如果子组件有文本设置,则相应的文本内容会显示在按钮内部。 默认尺寸为:高为28vp,宽无默认值。 |
Switch | 提供开关样式。 |
开关状态切换时触发该事件。
onChange(callback: (isOn: boolean) => void)
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
isOn | boolean | 是 | 为true时,代表状态从关切换为开。false时,代表状态从开切换为关。 |
本示例演示联系人管理功能页面。
可以新增,删除,收藏,展开手机号登功能。
使用到的组件间相互通信功能
@Prop装饰器:父子单向同步
@Link装饰器:父子双向同步
@Watch装饰器监听状态变量的变化
@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化
@Extend装饰器:定义扩展组件样式
Toggle组件
// 定义变量ID,默认从1开始,自增 let id = 1 // @Observed装饰的类 @Observed class Person { name: string phone: string isCollect: boolean = false id: number constructor(name: string, phone: string) { // id自增 this.id = id++ this.name = name this.phone = phone } } // 随机姓名方法,为了演示简写 function getRandomName() { return "张三" + Math.floor(Math.random() * 100) } //随机手机号,为了演示简写 function getRandomPhone() { return "1" + (Math.floor(Math.random() * 9000000000) + 1000000000) } @Entry @Component struct ContactsList { // 联系人列表 @State contactsList: Person[] = [new Person(getRandomName(), getRandomPhone()), new Person(getRandomName(), getRandomPhone())] // 当前展开的联系人ID @State currentExpandID: number = 0 // 是否点击选中 @State isSelect: boolean = false // 选中的联系人ID列表 @State selectIdList: number[] = [] build() { Column() { Row({ space: 10 }) { Text("联系人管理") .fontSize(20) Blank() Button(this.isSelect ? "取消" : "选中") // 扩展组件样式 .globalButtonStyle(Color.Gray) // 点击切换选中/取消按钮事件 .onClick(() => { this.isSelect = !this.isSelect this.selectIdList = [] }) Button("+") // 扩展组件样式 .globalButtonStyle(Color.Gray) .onClick(() => { // 新增联系人 this.contactsList.push(new Person(getRandomName(), getRandomPhone())) }) } .width("100%") .padding(10) List({ space: 10 }) { ForEach(this.contactsList, (item: Person) => { ListItem() { // 观察对象类属性变化,要配合自定义组件使用 ContactsItem({ item, currentExpandID: $currentExpandID, isSelect: this.isSelect, selectIdList: $selectIdList }) } }) }.padding(10) .layoutWeight(1) if (this.isSelect) { Button("删除") .margin(10) // 扩展组件样式 .globalButtonStyle(Color.Red) // 删除按钮点击事件 .onClick(() => { this.contactsList = this.contactsList.filter((item: Person) => { return !this.selectIdList.includes(item.id) }) }) } } .width('100%') .height('100%') .backgroundColor("#f7f7f7") } } // 自定义组件 @Component struct ContactsItem { // 数据双向同步,需要搭配@ObjectLink @ObjectLink item: Person // 组件内状态 @State isExpand: boolean = false // 父子双向同步 监听状态变化 @Link @Watch("onChangeCurrentID") currentExpandID: number // 父子单向同步 @Prop isSelect: boolean // 父子双向同步 @Link selectIdList: number[] // 监听状态变量变化回调 onChangeCurrentID() { if (this.item.id != this.currentExpandID) { this.isExpand = false } } build() { Column() { Row({ space: 10 }) { // 复选框 if (this.isSelect) { Toggle({ type: ToggleType.Checkbox }) // 选中状态发生变化时的事件 .onChange((val) => { if (val) { this.selectIdList.push(this.item.id) } else { let index: number = this.selectIdList.indexOf(this.item.id) this.selectIdList.splice(index, 1) } }) } // 头像 Image($r("app.media.picture")) .width(30) .height(30) // 姓名 Text(this.item.name) .fontSize(18) Blank() // 收藏 Image(this.item.isCollect ? $r("app.media.collect_select") : $r("app.media.collect")) .width(26) .height(26) .onClick(() => { // 第二层的属性值变化 this.item.isCollect = !this.item.isCollect }) } .height(40) .width("100%") // 手机号 if (this.isExpand) { Divider() .margin({ top: 10, bottom: 6 }) .color("#EEEEEE") Row() { Text("手机号码:" + this.item.phone) .fontSize(16) } .height(30) .width("100%") } } .width("100%") .padding(10) .borderRadius(6) .backgroundColor(Color.White) // 点击展开显示手机号码 .onClick(() => { this.isExpand = !this.isExpand this.currentExpandID = this.item.id }) } } // 定义扩展组件样式 @Extend(Button) function globalButtonStyle(color: Color) { .height(30) .fontSize(14) .backgroundColor(color) }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。