HarmonyOS 鸿蒙Next @BuilderParam为什么无法形成父子组件关系?
HarmonyOS 鸿蒙Next @BuilderParam为什么无法形成父子组件关系?
@Component
export struct Scope {
@Provide vertical: Length = default_vertical
@Provide horizontal: Length = default_horizontal
@Provide round: Length = default_round
@BuilderParam
content: () => void
build() {
Stack() {
this.content()
}
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
这是父组件。
@Component
export struct AppButton {
@Consume vertical: Length
@Consume horizontal: Length
@Consume round: Length
build() {
Button(‘test’)
.padding({
left: this.horizontal,
top: this.vertical,
right: this.horizontal,
bottom: this.vertical
})
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
这是子组件。
Scope({ vertical: 10 }) {
AppIconButton()
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
这是用例,运行后报错:
Error message:@Component ‘AppButton’[8] missing @Provide property with name vertical.
Fail to resolve @Consume(vertical).
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
将Scope中的全部@Provide声明参数移动到@Entry级别下后成功运行。
你的代码这种尾随闭包产生的结果是AppIconButton组合所在的上下文位置是在调用的代码作用域中,即AppIconButton的父组件成了调用时所在组件(估计是[@Entry](/user/Entry)组件),而Scope也在此位置被调用,则两者成为同级关系而非父子组件关系,因此[@Provide](/user/Provide)和[@Consume](/user/Consume)无法实现预想的效果,用简单测试可证实:
在三个组件都准备一个成员变量 label: string = 'xxx'; 分别写上各位置的标记字符串,然后在尾随闭包中调用AppIconButton()前面加上Text(this.label).fontsize(20);运行代码后会看到显示的是调用AppIconButton所在组件内的label变量所指的字符串,证实这种尾随闭包编译后的效果;这和编译器处理尾随闭包的机制相关,文档没有说明,只能测试证实。
另外,把尾随闭包改换成一个普通[@Builder](/user/Builder)构建函数后再用 content: this.mBuilder 这种变量赋值方式传递给Scope则可实现预期的父子关系;当然,了解了尾随闭包的真实上下文关系,在调用组件中使用[@Provide](/user/Provide)也得到同样结果。
还真是这样,他们无法成为父子组件关系,不知道这是有意为之还是bug。
也可能开发功能时没有考虑到这么多细节组合情况,毕竟语法组合数量太大,最终效果还得看编译器具体处理,官方语法大师可能也不能确定,只有实测不骗人,而且工具在升级,同样语法不同版本可能就不一样效果了:)
看下这个,说到了[@BuilderParam](/user/BuilderParam)使用的时候,[@Provide](/user/Provide)没有被创建的问题,感觉跟你现在遇到的问题差不多。
常见问题 @BuilderParam尾随闭包情况下@Provide未定义错误 在此场景下,CustomWidget执行this.builder()创建子组件CustomWidgetChild时,this指向的是HomePage。因此找不到CustomWidget的@Provide变量,所以下面示例会报找不到@Provide错误,和@BuilderParam连用的时候要谨慎this的指向。
错误示例:
class Tmp { a: string = ‘’ }
@Entry
@Component
struct HomePage {
@Builder
builder2($$: Tmp) {
Text(${$$.a}测试
)
}
build() { Column() { CustomWidget() { CustomWidgetChild({ builder: this.builder2 }) } } } }
@Component struct CustomWidget { @Provide(‘a’) a: string = ‘abc’; @BuilderParam builder: () => void;
build() { Column() { Button(‘你好’).onClick((x) => { if (this.a == ‘ddd’) { this.a = ‘abc’; } else { this.a = ‘ddd’; }
})
this.builder()
}
} }
@Component struct CustomWidgetChild { @Consume(‘a’) a: string; @BuilderParam builder: ($$: Tmp) => void;
build() { Column() { this.builder({ a: this.a }) } } }
就是这段描述
从你测试来看,AppButton只能在Scope的build()或者是Scope子view下才能生效;
可能是[@Provide](/user/Provide)还没有注册成功(猜测)。
Scope({ vertical: 10 }) { AppIconButton() }这个不表示AppIconButton在是Scope的build()之后才使用,因为可以放在其他view的build()里面调用;
你改成
[@Component](/user/Component) export struct Scope {
[@Provide](/user/Provide) vertical: Length = default_vertical
[@Provide](/user/Provide) horizontal: Length = default_horizontal
[@Provide](/user/Provide) round: Length = default_round
[@BuilderParam](/user/BuilderParam) content: () => void
build() {
Stack() { AppIconButton() }
}
}
试试。
没有看到完整的代码,不知道存不存在使用[@BuilderParam](/user/BuilderParam),可能存在一个this指向问题;
因为现在鸿蒙存在的问题比较多,所以还是先按照文档上中规中矩的用比较靠谱。
在HarmonyOS鸿蒙系统中,@BuilderParam
注解主要用于自定义组件时,通过Builder模式来构建组件的属性。若@BuilderParam
无法形成预期的父子组件关系,通常可能是以下几个原因导致的:
-
注解使用不当:确保
@BuilderParam
被正确地应用于需要构建的属性上,并且属性类型与父组件接收的类型一致。 -
组件定义问题:检查父子组件的定义,确保父组件能够正确解析和接收子组件。子组件的注册和导入是否正确,以及是否遵循了鸿蒙系统的组件通信和嵌套规则。
-
XML布局文件错误:如果在XML中定义组件关系,检查是否有语法错误或标签不匹配的情况,确保父组件能够包含子组件。
-
版本兼容性问题:不同版本的鸿蒙系统可能对组件和注解的支持有差异,确保开发环境与目标设备系统版本兼容。
-
编译与运行时环境:检查开发工具的版本和配置,确保编译环境正确无误,同时运行时环境也支持所使用的组件和特性。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。