HarmonyOS鸿蒙Next中请教个组件封装的问题
HarmonyOS鸿蒙Next中请教个组件封装的问题
我想封装个通用的按钮组件,Button()相关的属性只能通过参数传递进来吗?比如我外部有的地方需要设置按钮高度有的不需要,就只能通过下边代码里的buttonHeight参数传递吗?要想控制Button()的其它属性都需要挨个写参数?
```typescript
[@ComponentV2](/user/ComponentV2)
export struct PrimaryTextButton {
[@Require](/user/Require) [@Param](/user/Param) text: string | Resource
[@Event](/user/Event) onButtonClick(): void | Promise<void>
[@Param](/user/Param) buttonHeight?: Length = '78lpx'
[@Param](/user/Param) buttonPadding?: Padding = { left: '50lpx', right: '50lpx' }
[@Param](/user/Param) buttonEnabled: boolean = true
private loading: boolean = false
[@Local](/user/Local) private fontColor: ResourceColor = Color.White
[@Local](/user/Local) private bgColor: ResourceColor = appTheme.colors.primary
[@Local](/user/Local) private showLoading: boolean = false
build() {
Button() {
Row() {
Text(this.text)
.fontSize('28lpx')
.fontColor(this.fontColor)
if (this.showLoading) {
LoadingProgress()
.width('50lpx')
.height('50lpx')
}
}
}
.height(this.buttonHeight)
.backgroundColor(this.bgColor)
.padding(this.buttonPadding ?? {})
.enabled(this.buttonEnabled && !this.loading)
.onClick(() => {
if (!this.buttonEnabled || this.loading) {
return
}
const r: void | Promise<void> = this.onButtonClick()
if (r instanceof Promise) {
this.loading = true
this.checkAnimation()
r.finally(() => setTimeout(() => {
this.loading = false
this.checkAnimation()
}))
}
})
}
[@Monitor](/user/Monitor)('buttonEnabled')
private enableStateChanged(_: IMonitor) {
this.checkAnimation()
}
private checkAnimation() {
const b = this.buttonEnabled && !this.loading
this.getUIContext()?.animateTo({
duration: 250,
curve: Curve.Friction
}, () => {
this.fontColor = b ? Color.White : appTheme.colors.disabledText
this.bgColor = b ? appTheme.colors.primary : appTheme.colors.disabledBg
this.showLoading = this.loading
})
}
}
更多关于HarmonyOS鸿蒙Next中请教个组件封装的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
@Component struct MyButton { buttonHeight: number; // 控制按钮高度的参数 buttonText: string; // 控制按钮文本的参数
build() {
Button(this.buttonText)
.height(this.buttonHeight)
.width(100)
.backgroundColor('f00')
.onClick(() => {
console.log('Button onClick');
})
.onTouch((event) => {
console.log('Button onTouch');
event.stopPropagation();
})
}
}
更多关于HarmonyOS鸿蒙Next中请教个组件封装的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
我想给按钮加个通用的loading状态,这个应该是根据onClick返回的Promise来判断loading,属性修改器好像不行?
可以试试用@Extend来 进行传参
[@Extend](/user/Extend)(Button) function fancy (widths?:number,heights?:number,bgcol?:string) {
.width(widths)
.backgroundColor(bgcol)
.height(heights)
}
Button()
.fancy(undefined,100,'#666')
@Extend好像不支持跨文件使用?而且我想要封装一个带loading的按钮,用这个好像也不行,
那你试试这个三方库看可不可以满足你的需求:[@ibestservices/ibest-ui](https://ibestui.ibestservices.com/components/button/#button-按钮)
在HarmonyOS Next中封装组件需使用ArkUI框架。组件封装主要涉及三种文件:.ets(UI结构)、.json(组件配置)、.style(样式)。通过@Component装饰器声明自定义组件,使用@Builder构建可复用UI片段,@Styles定义可复用样式。组件通信采用Prop/State机制,父组件通过Prop传递数据,子组件使用@Link或@ObjectLink实现双向绑定。生命周期管理提供aboutToAppear和aboutToDisappear回调。封装时需注意组件独立性,避免对外部状态直接依赖。
在HarmonyOS Next中封装通用按钮组件时,确实可以通过参数传递Button属性,但这不是唯一方式。更优雅的做法是使用Builder模式或属性代理:
- 使用@BuilderParam接收外部样式:
@ComponentV2
export struct PrimaryTextButton {
[@BuilderParam](/user/BuilderParam) buttonStyle?: (button: Button) => void
build() {
Button() {
// 内容
}
.apply(this.buttonStyle) // 应用外部传入的样式
}
}
// 使用时:
PrimaryTextButton({
buttonStyle: (btn) => {
btn.height('100lpx').width('200lpx')
}
})
- 使用扩展方法复用样式:
function primaryStyle(button: Button): Button {
return button.height('78lpx').padding({left:'50lpx',right:'50lpx'})
}
// 在组件中直接调用
Button().apply(primaryStyle)
- 对于必须参数建议保留@Param,可选样式建议使用BuilderParam。这样既保证了核心功能的可控性,又提供了样式定制的灵活性。
这种模式比逐个参数传递更灵活,也更容易维护。Builder模式特别适合需要高度定制样式的组件封装场景。