鸿蒙自定义弹出框响应式更新数据

1.原因:

openCustomDialog不支持自定义组件使用@Reusable@Link@Provide@Consume等装饰器,来同步弹出框弹出的页面与ComponentContent中自定义组件的状态

2.解决

class Params { // 要调用@Component里面的方法需要使用参数接收
  onClose?: () => void; // 关闭弹窗方法
  selStockroom?: (index:number) => void; // 选择方法
  stockroomList: IPartsStockItem[]; // 数据传入

  constructor(onClose?: () => void, stockroomList?: IPartsStockItem[], selStockroom?: (index:number) => void) { // 通过constructor接收
    this.onClose = onClose;
    this.stockroomList = stockroomList || [];
    this.selStockroom = selStockroom
  }
}

@Builder
function shareDialog(params: Params) { // 弹框主体
  Column() {
    Row() {
      Text('请选择仓库')
        .fontColor('#333')
        .fontSize(fts('33lpx'))
        .margin({ bottom: '40lpx' })
    }
    .width('100%')
    .justifyContent(FlexAlign.Center)

    Column() {
      ForEach(params.stockroomList, (item: IPartsStockItem, i: number) => {
        Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
          Text(item.name).fontSize(fts("32lpx"))
          if (item.selected) {
            Image($rawfile("icon/fukuanzhong_ico_select.png")).width("32lpx").height("32lpx")
          } else {
            Image($rawfile("icon/fukuanzhong_ico_noselect.png")).width("32lpx").height("32lpx")
          }
        }
        .onClick(() => {
          params.selStockroom?.(i) // 通过params调用@Component方法
        })
        .margin({ bottom: "24lpx" })
      })
    }
  }
  .backgroundColor('#FFFFFF')
  .width('70%')
  .padding('60lpx')
  .borderRadius('20lpx')
}
@Component
export struct PartsCollection {
  
controller: SearchController = new SearchController();
  @State stockroomList: IPartsStockItem[] = []
  private contentNode: ComponentContent<Object> =
  new ComponentContent(this.ctx, wrapBuilder(shareDialog), new Params((): void => this.closeDialog(), this.stockroomList)) // 创建conetntNode,此时不可以传入异步数据,否则会是undefined
  private options: promptAction.BaseDialogOptions = { alignment: DialogAlignment.Center, offset: { dx: 0, dy: 50 } } // 设置弹框显示位置

openDialog() {
if (this.contentNode !== null) {
// 确保传递正确的参数类型
this.contentNode = new ComponentContent(
this.ctx,
wrapBuilder(shareDialog),
new Params((): void => this.closeDialog(), this.stockroomList, (index:number): void => this.selStockroom(index)) // 此时可以传入异步数据
);
this.ctx.getPromptAction()
.openCustomDialog(this.contentNode, this.options)
.then(() => {
Log.info('OpenCustomDialog complete.')
})
.catch((error: BusinessError) => {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
Log.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
})
}
}

closeDialog() {
if (this.contentNode !== null) {
this.ctx.getPromptAction()
.closeCustomDialog(this.contentNode)
.then(() => {
Log.info('closeCustomDialog complete.')
})
.catch((error: BusinessError) => {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
Log.error(`closeCustomDialog args error code is ${code}, message is ${message}`);
})
}
}

selStockroom(index: number) {
const arr = [...this.stockroomList]
for (let i = 0; i < arr.length; i++) {
arr[i].selected = index == i;
}
this.stockroomList = arr // 修改了传入的数据
if (this.contentNode) {
this.contentNode.update( // 动态修改传入的数据,让数据更新达到响应式效果
new Params(
(): void => this.closeDialog(),
this.stockroomList, // 传递已更新的列表
(index: number): void => this.selStockroom(index)
)
);
}
}

}

 

posted on 2025-09-26 09:46  ChoZ  阅读(21)  评论(0)    收藏  举报

导航