HarmonyOS 鸿蒙Next 组件间的状态管理困难
HarmonyOS 鸿蒙Next 组件间的状态管理困难
目标及问题
问题:
下拉菜单中只有一个文件。更新的列表数据没能同步到这个选择组件中。
主界面的相关代码:
变量声明部分:
@Entry
@Component
struct ScanPageIndex {
private breakpointSystem: BreakpointSystem = new BreakpointSystem()
@StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm'
[@State](/user/State) dir: string = 'Ld';
[@State](/user/State) cfglist: string[] = [];
[@State](/user/State) linlist: string[] = [];
[@State](/user/State) pagetitle: string = '连接设备';
[@State](/user/State) SSIDnotEmpty: boolean = false;
[@State](/user/State) PWDnotEmpty: boolean = false;
[@State](/user/State) ssid: string = "";
[@State](/user/State) fileisSelect: boolean = false;
组件调用部分:
Button("创建配置")
.fontSize(20)
.height(40)
.width(150)
.fontWeight(FontWeight.Bold)
.onClick(async () => {
FileUtils.newFile('/' + this.cfgFileName);
this.filelist = await FileUtils.listFiles(getContext(this).filesDir,'.cfg','.csv');
ToastUtils(this.filelist.length.toString());
this.cfglist = await FileUtils.listFiles(getContext(this).filesDir,'.cfg');
this.cfglen = this.cfglist.length;
this.linlist = await FileUtils.listFiles(getContext(this).filesDir,'.csv');
this.linlen = this.linlist.length;
})
}
if(this.cfglist.length) SelectExt({SelectIndex:0,seletTitle:'选择配置文件',thisSetID:0,RecordTitle:'cfgFile',tobeRecord:false,seletItems: this.cfglist })
if(this.linlist.length) SelectExt({SelectIndex:0,seletTitle:'选择线性配置',thisSetID:1,RecordTitle:'linarFile',tobeRecord:false,seletItems:this.linlist})
// [@State](/user/State) SelectIndex:number=0;
组件的实现代码
const TAG = 'SelectExt'
@Component
export struct SelectExt {
[@State](/user/State) SelectIndex:number=0;
[@State](/user/State) thisSetID:number=0;
[@State](/user/State) seletItems:Array<string>=[];
[@State](/user/State) seletTitle:string='';
[@State](/user/State) RecordTitle:string='';
[@State](/user/State) tobeRecord:boolean=false
@Builder settingItem($$:{settingId: number, icon: Resource, title: string | Resource, showDivider: boolean}) {
Stack() {
if ($$.settingId == this.thisSetID) {
Column() {
Column()
.backgroundColor(get_translucentSaturation_accent())
.height('100%')
.width('100%')
.borderRadius(16)
}
.height('100%')
.width('100%')
.padding(3)
}
Column() {
Row() {
Image($$.icon)
.height(24)
.width(24)
Text($$.title)
.fontColor($r('app.color.text_level1'))
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ left: 16 })
}
.height(56)
if ($$.showDivider) {
Column() {
Divider().width('100%').color($r('app.color.divider'))
}.padding({ left: 40 })
}
}
.padding({ left: 12, right: 12 })
.alignItems(HorizontalAlign.Start)
.width('100%')
}
.height(56)
.width('100%')
}
@Builder settingSubTitle($$:{text: string}) {
Row() {
Text($$.text)
.fontWeight(FontWeight.Medium)
.fontColor($r('app.color.text_level2'))
.fontSize(14)
Image($r('app.media.ic_arrow_right'))
.width(12)
.height(24)
.margin({ left: 4 })
}
.padding({ right: 12 })
.justifyContent(FlexAlign.End)
}
@Builder selectMenu($$:{thisResource: Array<SelectionItem>, outPut: (value: number) => number}) {
Column() {
Column() {
ForEach($$.thisResource, (item: SelectionItem, index: number) => {
Column() {
Column() {
Text(item.title)
.fontColor(item.index == $$.outPut(-1) ? get_accent() : $r('app.color.text_level1'))
.fontSize(14)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
.padding({ bottom: 12, top: 12 })
.onTouch(() => {
$$.outPut(item[1])
console.info($$.outPut(-1).toString())
})
if (index != $$.thisResource.length - 1)
Divider().color($r('app.color.divider'))
}
.width('100%')
})
}
.padding({ left: 12, right: 12 })
}
.width(112)
.justifyContent(FlexAlign.Start)
}
@Builder settingSelect($$:{thisResource: Array<SelectionItem>, outPut: (value: number) => number}) {
Row() {
Text($$.thisResource[$$.outPut(-1)][0])
.fontColor($r('app.color.text_level1'))
.fontSize(16)
.fontWeight(FontWeight.Medium)
Image($r('app.media.ic_spinner_level1'))
.width(24)
.height(24)
}
.bindMenu(this.selectMenu({thisResource: $$.thisResource, outPut: $$.outPut}))
.padding({ right: 12 })
.justifyContent(FlexAlign.End)
}
build() {
Column() {
Stack({ alignContent: Alignment.End }) {
this.settingItem({
settingId: 9,
icon: $r('app.media.ic_setting_calendarSet'),
title: this.seletTitle,
showDivider: true
})
this.settingSelect({ thisResource: builtSelectArray(this.seletItems), outPut: (value: number) => {
if (value > -1) {
this.SelectIndex = value
if(this.tobeRecord)AppStorage.set(this.RecordTitle, value.toString());
}
return this.SelectIndex
} })
}.height(56).width('100%')
}
.width('100%')
}
}
依据我的理解,主界面中的linlist 和 cfglist 都是@State,一旦创建文件后必然同步更新这两个列表数据。但是SelectExt的seletItems列表数据,只是在linList.len>0才更新一次。无法多次同步数据。又不能@provide, @Customer,因为这两个组件的数据源不一致。请大师指教
更多关于HarmonyOS 鸿蒙Next 组件间的状态管理困难的实战教程也可以访问 https://www.itying.com/category-93-b0.html
太复杂的数据传递,建议用emitter吧
更多关于HarmonyOS 鸿蒙Next 组件间的状态管理困难的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
不好意思,感觉@state @link 可以搞定。但是SelectExt的一个函数还是有问题。下面是测试程序
import { SelectExt } from '../common/utils/selectExt';
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State text:string ='';
@State filelist:string[]=[];
@State cfglist:string[]=[];
@State linlist:string[]= [];
build() {
Row() {
Column() {
List({ space: 5, initialIndex: 0 }) {
ForEach(this.cfglist, (item) => {
ListItem() {
Text('' + item)
.width('100%').height(40).fontSize(20)
.textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF)
}
}, item => item)
}
.listDirection(Axis.Vertical) // 排列方向
.divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果
.onScrollIndex((firstIndex: number, lastIndex: number) => {
console.info('first' + firstIndex)
console.info('last' + lastIndex)
})
.width('90%')
TextInput({text:this.text,placeholder:'test intput hear'})
.fontSize(40)
.height(60)
.width('80%')
.backgroundColor('yellow')
.onChange((value:string)=>{
this.text=value;
})
Button('添加')
.fontSize(40)
.height(60)
.onClick(()=>{
this.filelist.push(this.text);
if( this.text.indexOf('.cfg')>0)this.cfglist.push( this.text);
if( this.text.indexOf('.csv')>0)this.linlist.push( this.text);
})
SelectExt({SelectIndex:0,seletTitle:'选择配置文件',thisSetID:0,RecordTitle:'cfgFile',tobeRecord:false,seletItems: $cfglist })
SelectExt({SelectIndex:0,seletTitle:'选择线性配置',thisSetID:1,RecordTitle:'linarFile',tobeRecord:false,seletItems: $linlist})
}
.width('100%')
}
.height('100%')
}
}
在HarmonyOS鸿蒙Next中,组件间的状态管理主要通过以下几种机制实现:
-
@State和@Prop:@State用于定义组件内部的状态,当状态变化时,组件会自动重新渲染。@Prop用于父组件向子组件传递状态,子组件可以读取但不能直接修改父组件的状态。
-
@Observed和@ObjectLink:用于管理复杂对象的状态。@Observed标记的类会被系统观察,当对象属性变化时,@ObjectLink绑定的组件会自动更新。
-
@Watch:用于监听状态变化,当指定状态发生变化时,会触发回调函数。
-
全局状态管理:通过AppStorage或LocalStorage实现全局状态管理,AppStorage用于应用全局状态,LocalStorage用于页面级别的状态管理。
这些机制提供了灵活的状态管理方式,开发者可以根据具体需求选择合适的方案。