網(wǎng)站地圖對seo的影響品牌營銷策劃與管理
【HarmonyOS】@Observed和@ObjectLink嵌套對象屬性更改UI不刷新問題
一、問題背景
使用了@Observed和@ObjectLink,修改嵌套對象的屬性,UI還是不刷新,常見的問題有以下三種形式:
1.多級嵌套,嵌套對象的類并沒有添加@Observed進行監(jiān)聽
2.多級嵌套,嵌套對象的View組件沒有抽離出來,添加@ObjectLink進行該級對象的監(jiān)聽綁定
3.嵌套對象,并沒有new出來創(chuàng)建,直接賦值沒有創(chuàng)建對象的過程,無法激活Observed監(jiān)聽
二、代碼舉例
以代碼示例舉例:
1.創(chuàng)建了接口TestInfoInterFace ,父類TestInfo,嵌套類TestItem 。
interface TestInfoInterFace {name: string;items: TestItem[];
}class TestItem {content: string = "";isClicked: boolean = false;
}
class TestInfo {name: string;items: TestItem[];constructor(name: string, items: TestItem[]) {this.name = name;this.items = items;}
}
2.添加測試數(shù)據(jù),渲染列表,單元格數(shù)據(jù)基本類型結(jié)構(gòu)為TestInfo。
TestPage { mTestDataArr: TestInfo[] = [new TestInfo('測試數(shù)據(jù)1', [{content: '單元數(shù)據(jù)1',isClicked: false}, {content: '單元數(shù)據(jù)1',isClicked: false}]),new TestInfo('測試數(shù)據(jù)2', [{content: '單元數(shù)據(jù)1',isClicked: false}, {content: '單元數(shù)據(jù)1',isClicked: false}]),new TestInfo('測試數(shù)據(jù)3', [{content: '單元數(shù)據(jù)1',isClicked: false}, {content: '單元數(shù)據(jù)1',isClicked: false}]),]build() {Column() {ForEach(this.mTestDataArr, (item: TestInfoInterFace) => {ChildView({mTestInfo: item})})}.width('100%').height('100%')}
}
struct
3.抽離嵌套組件ChildView ,綁定雙向監(jiān)聽。
export struct ChildView {private TAG: string = "TestPage"; mTestInfo: TestInfobuild() {Column() {Text(this.mTestInfo.name).backgroundColor(Color.Red).fontSize(px2fp(52))ForEach(this.mTestInfo.items, (tempInfo: TestItem) => {Text(tempInfo.content).fontSize(px2fp(52)).backgroundColor(tempInfo.isClicked ? Color.Blue : Color.Yellow).onClick(() => {tempInfo.isClicked = !tempInfo.isClickedconsole.log(this.TAG, JSON.stringify(tempInfo))})})Divider()}}
}
渲染界面后的效果為:
此時我們點擊單元數(shù)據(jù)1或者2,去修改isClicked選中狀態(tài),并不會刷新UI,整個代碼有以上總結(jié)的三個問題:
1.TestItem 多級嵌套,嵌套對象的類并沒有添加@Observed進行監(jiān)聽
2.ChildView 多級嵌套了一個層級,直接就進行了循環(huán)渲染,其嵌套對象的View組件沒有抽離出來,添加@ObjectLink進行該級對象的監(jiān)聽綁定
3.mTestDataArr嵌套對象中的TestItem并沒有new出來創(chuàng)建,是通過花括號直接賦值沒有創(chuàng)建對象的過程,無法激活Observed監(jiān)聽
三、完整DEMO示例:
interface TestInfoInterFace {name: string;items: TestItem[];
}// TODO 問題1:多層級時,需要逐個層級進行類監(jiān)聽
class TestItem {content: string = "";isClicked: boolean = false;constructor(content: string, isClicked: boolean) {this.content = content;this.isClicked = isClicked;}
}
class TestInfo {name: string;items: TestItem[];constructor(name: string, items: TestItem[]) {this.name = name;this.items = items;}
}
struct TestPage {// TODO 問題3 每個被設(shè)置Observed的對象,需要new出來創(chuàng)建,才能激活監(jiān)聽,花括號的形式賦值,并不會激活監(jiān)聽。 mTestDataArr: TestInfo[] = [new TestInfo('測試數(shù)據(jù)1', [new TestItem('單元數(shù)據(jù)1', false), new TestItem('單元數(shù)據(jù)2', false)]),new TestInfo('測試數(shù)據(jù)2', [new TestItem('單元數(shù)據(jù)1', false), new TestItem('單元數(shù)據(jù)2', false)]),new TestInfo('測試數(shù)據(jù)3', [new TestItem('單元數(shù)據(jù)1', false), new TestItem('單元數(shù)據(jù)2', false)]),// new TestInfo('測試數(shù)據(jù)1', [{// content: '單元數(shù)據(jù)1',// isClicked: false// }, {// content: '單元數(shù)據(jù)1',// isClicked: false// }]),// new TestInfo('測試數(shù)據(jù)2', [{// content: '單元數(shù)據(jù)1',// isClicked: false// }, {// content: '單元數(shù)據(jù)1',// isClicked: false// }]),// new TestInfo('測試數(shù)據(jù)3', [{// content: '單元數(shù)據(jù)1',// isClicked: false// }, {// content: '單元數(shù)據(jù)1',// isClicked: false// }]),]build() {Column() {ForEach(this.mTestDataArr, (item: TestInfoInterFace) => {ChildView({mTestInfo: item})})}.width('100%').height('100%')}
}
export struct ChildView {private TAG: string = "TestPage"; mTestInfo: TestInfobuild() {Column() {Text(this.mTestInfo.name).backgroundColor(Color.Red).fontSize(px2fp(52))// TODO 多層級時,需要逐個層級進行剝離,創(chuàng)建子組件和綁定雙向監(jiān)聽。// ForEach(this.mTestInfo.items, (tempInfo: TestItem) => {// Text(tempInfo.content)// .fontSize(px2fp(52))// .backgroundColor(tempInfo.isClicked ? Color.Blue : Color.Yellow)// .onClick(() => {// tempInfo.isClicked = !tempInfo.isClicked// console.log(this.TAG, JSON.stringify(tempInfo))// })// })ForEach(this.mTestInfo.items, (tempInfo: TestItem) => {ItemView({mItem: tempInfo}).margin({top: px2vp(100)})})Divider()}}
}
export struct ItemView {private TAG: string = "TestPage"; mItem: TestItembuild() {Text(this.mItem.content).fontSize(px2fp(52)).backgroundColor(this.mItem.isClicked ? Color.Blue : Color.Yellow).onClick(() => {this.mItem.isClicked = !this.mItem.isClickedconsole.log(this.TAG, JSON.stringify(this.mItem))})}
}