HarmonyOS鸿蒙Next中如何实现自定义通用组件?@BuilderParam和@Component
HarmonyOS鸿蒙Next中如何实现自定义通用组件?@BuilderParam和@Component 多个页面使用相似的卡片样式,希望封装成通用组件,支持自定义内容。
原理解析
HarmonyOS ArkUI提供了组件化开发能力:
- @Component装饰器定义自定义组件
- @BuilderParam接收外部传入的UI构建函数
- 通过属性传递配置参数
解决步骤
步骤1:定义通用卡片组件
import { Colors, BorderRadius, Spacing } from '../constants/Colors';
[@Component](/user/Component)
export struct CardView {
[@BuilderParam](/user/BuilderParam) content: () => void; // 接收外部UI内容
padding: number = Spacing.lg;
marginH: number = Spacing.xl;
marginV: number = Spacing.md;
build() {
Column() {
if (this.content) {
this.content()
}
}
.width('100%')
.padding(this.padding)
.margin({ left: this.marginH, right: this.marginH, top: this.marginV, bottom: this.marginV })
.backgroundColor(Colors.cardBackground)
.borderRadius(BorderRadius.lg)
.border({ width: 1, color: Colors.border })
.shadow({ radius: 4, color: '#0000000a', offsetY: 2 })
}
}
步骤2:定义渐变卡片组件
[@Component](/user/Component)
export struct GradientCard {
[@BuilderParam](/user/BuilderParam) content: () => void;
padding: number = Spacing.xl;
marginH: number = Spacing.xl;
build() {
Stack() {
// 渐变背景
Column()
.width('100%')
.height('100%')
.linearGradient({
angle: 135,
colors: [[Colors.primary, 0], [Colors.primaryLight, 1]]
})
.borderRadius(BorderRadius.xl)
// 内容
Column() {
if (this.content) {
this.content()
}
}
.width('100%')
.padding(this.padding)
}
.width('100%')
.margin({ left: this.marginH, right: this.marginH })
.borderRadius(BorderRadius.xl)
.shadow({ radius: 8, color: '#06575840', offsetY: 4 })
}
}
步骤3:使用自定义组件
import { CardView, GradientCard } from '../components/CardView';
@Entry
[@Component](/user/Component)
struct MyPage {
build() {
Column() {
// 使用普通卡片
CardView({ padding: 16 }) {
Column({ space: 8 }) {
Text('卡片标题').fontSize(16).fontWeight(FontWeight.Bold)
Text('卡片内容描述').fontSize(14).fontColor('#666')
}
}
// 使用渐变卡片
GradientCard() {
Column({ space: 8 }) {
Text('渐变卡片').fontSize(18).fontColor('#fff')
Text('漂亮的渐变背景').fontSize(14).fontColor('#ddd')
}
}
}
}
}
步骤4:定义颜色常量(统一管理)
// Colors.ets
export const Colors = {
primary: '#065758',
primaryLight: '#00999F',
cardBackground: '#ffffff',
textPrimary: '#0d121b',
textSecondary: '#6b7280',
border: '#e5e7eb'
}
export const Spacing = {
sm: 8,
md: 12,
lg: 16,
xl: 20
}
export const BorderRadius = {
md: 8,
lg: 12,
xl: 16
}
效果图
封装通用组件 → 统一样式管理 → 多处复用 → 修改一处全局生效
更多关于HarmonyOS鸿蒙Next中如何实现自定义通用组件?@BuilderParam和@Component的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,使用@BuilderParam装饰器实现自定义通用组件。@BuilderParam用于声明自定义构建函数类型的属性,允许父组件传递UI构建逻辑给子组件。子组件通过@BuilderParam属性接收并调用该构建函数,实现动态UI组合。@Component装饰器用于定义可复用的自定义组件,封装内部UI结构和行为。两者结合可实现灵活、可复用的通用组件。
在HarmonyOS Next中,使用[@BuilderParam](/user/BuilderParam)和[@Component](/user/Component)装饰器是实现自定义通用组件的核心方案,尤其适合封装可复用的卡片式UI。
核心实现步骤:
-
定义组件结构(@Component) 使用
[@Component](/user/Component)创建可复用的UI组件框架,定义卡片的固定布局(如标题栏、边框等)。[@Component](/user/Component) struct CustomCard { // 定义占位区域 } -
声明动态内容接口(@BuilderParam) 在组件内部使用
[@BuilderParam](/user/BuilderParam)声明一个或多个插槽,用于接收外部传入的自定义UI内容。[@Component](/user/Component) struct CustomCard { [@BuilderParam](/user/BuilderParam) contentBuilder: () => void // 或声明多个插槽:[@BuilderParam](/user/BuilderParam) headerBuilder: () => void } -
在组件布局中调用 在组件的
build()方法中,通过调用this.contentBuilder()来渲染外部传入的UI。build() { Column() { // 固定部分 Text('卡片标题') // 动态内容部分 this.contentBuilder() } } -
外部使用组件并传入内容 在使用该组件的页面中,通过
[@Builder](/user/Builder)定义要插入的自定义UI,并传递给组件。[@Builder](/user/Builder) function MyCustomContent() { Text('这是自定义内容') Button('按钮') } // 在页面中调用 CustomCard({ contentBuilder: this.MyCustomContent })
关键优势:
- 高复用性:一次封装,多处使用。
- 强灵活性:通过
[@BuilderParam](/user/BuilderParam)允许外部完全控制部分区域的UI和逻辑。 - 类型安全:ArkTS的静态类型检查确保传递内容的正确性。
典型应用场景:
- 统一视觉规范的卡片、弹窗、设置项。
- 列表项模板。
- 带有可变头部/底部/内容的容器组件。
这种方式实现了组件框架与具体内容的解耦,是HarmonyOS Next中构建可复用UI模块的标准实践。

