HarmonyOS 自定义控件怎么向外回传信息?

自定义一个控件,把子控件中回调的参数回传到应用层

自定义组件定义代码:

class Options {
  id: string = ''
  onLoad: Function =()=>{};
}

@Builder
function overBuilder(params: Options) {
  XComponent({
    id: params.id,
    libraryname: 'irtcrender',
    type: XComponentType.TEXTURE
  }).onLoad((iRtcRender: IRtcRender) => {
    if (params.onLoad) {
      params.onLoad(iRtcRender);
    }
  }).width('100%')
    .height('100%')
}

@Component
export struct IRtcComponent {
  @Prop Id: string;
  @Prop onLoad: Function;

  build() {
    overBuilder({ id: this.Id, onLoad: this.onLoad })
  }
}

应用调用代码:

IRtcComponent({
  Id: 'localRender',
  onLoad:(iRtcRender: IRtcRender) => {
    this.mLocalRender = iRtcRender;
    Logger.info(TAG, 'onLoad', `this.mLocalRender = ${JSON.stringify(this.mLocalRender)}`);
  }
})
  .alignRules({
    center: { anchor: '__container__', align: VerticalAlign.Center },
    middle: { anchor: '__container__', align: HorizontalAlign.Center }
  })
  .backgroundColor(Color.Black)
  .width('512px')
  .height('640px')

运行时crash日志:

Pid:22270
Uid:20020057
Reason:TypeError
Error name:TypeError
Error message:@Component '@Component 'IRtcComponent'[62]': Illegal variable value error with decorated variable undefined 'onLoad': failed validation: 'undefined, null, number, boolean, string, or Object but not function, not V3 @observed / @track class, attempt to assign value type: 'function', value: 'undefined'!
Stacktrace:
  at varValueCheckFailed (/usr1/hmos_for_system/src/increment/sourcecode/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:2173:1)
at checkIsSupportedValue (/usr1/hmos_for_system/src/increment/sourcecode/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:4883:1)
at SynchedPropertyOneWayPU (/usr1/hmos_for_system/src/increment/sourcecode/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:5371:1)
at SynchedPropertyObjectOneWayPU (/usr1/hmos_for_system/src/increment/sourcecode/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:0:1)
at IRtcComponent (irtc/Index.ets:98:1)
at anonymous (demo/src/main/ets/pages/Index.ets:622:34)
at updateFunc (/usr1/hmos_for_system/src/increment/sourcecode/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:6722:1)
at observeComponentCreation2 (/usr1/hmos_for_system/src/increment/sourcecode/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:6763:1)
at anonymous (demo/src/main/ets/pages/Index.ets:622:34)

应该怎么才可以把iRtcRender传给应用层

阅读 432
1 个回答

可以参考此段demo

@Entry
@Component
struct Index {
  @State @Watch('dataChange') data: ClickEvent | undefined = undefined

  dataChange() {
    if (this.data) {
      console.log("dataChange displayX:" + this.data.displayX.toString())
      console.log("dataChange displayY:" + this.data.displayY.toString())
    }
  }

  build() {
    Column() {
      myComponent({
        item: this.data,
        onItemClick: (event: ClickEvent | undefined) => {
          this.data = event
          if (event) {
            console.log("Index displayX:" + event.displayX.toString())
            console.log("Index displayY:" + event.displayY.toString())
          }
        }
      })
      Button("myStructButton")
        .onClick(() => {
          console.log("displayX:" + this.data?.displayX.toString())
          console.log("displayY:" + this.data?.displayY.toString())
        })
    }
  }
}

class Tmp {
  item: ClickEvent | undefined
  onItemClick = (event: ClickEvent): void => {
  }
}

@Builder
function myBuilder($$: Tmp) {
  Button("myBuilderButton")
    .onClick((event: ClickEvent) => {
      console.log("myBuilderButton displayX:" + event.displayX.toString())
      console.log("myBuilderButton displayY:" + event.displayY.toString())
      $$.onItemClick(event)
    })
}

@Component
export struct myComponent {
  @Link item: ClickEvent | undefined
  onItemClick = (event: ClickEvent): void => {
  }

  build() {
      myBuilder({ item: this.item, onItemClick: this.onItemClick })
  }
}