当前位置:首页>鸿蒙APP>鸿蒙自定义组件封装实战:复用、传参、双向绑定、样式抽离

鸿蒙自定义组件封装实战:复用、传参、双向绑定、样式抽离

  • 2026-10-29 11:29:43
鸿蒙自定义组件封装实战:复用、传参、双向绑定、样式抽离

一、前言

在鸿蒙项目开发中,重复编写按钮、卡片、列表项、弹窗等UI模块,会产生大量冗余代码,后续迭代维护成本陡增。ArkTS 依托 @Component 装饰器实现组件化开发,是提升开发效率、统一UI风格的核心手段。

  • 页面重复堆砌相同UI,修改样式需要逐个页面调整;

  • 父子组件数据流转混乱,入参刷新逻辑不清晰;

  • 不会实现双向绑定,子组件数据变更无法同步父组件;

  • 样式硬编码在组件内,难以实现全局换肤、样式统一管理;

  • 组件无渲染优化,出现无效重渲染,造成页面卡顿。

本文从基础组件封装入手,依次讲解父子传参、双向数据绑定、公共样式抽离、性能优化,配套完整可运行代码,帮你搭建项目标准化组件体系。

二、核心装饰器与组件分类

先理清常用装饰器作用与组件类型,是组件封装的基础。

装饰器/类型

使用场景

核心特性

@Entry

页面根组件

作为路由入口,全局唯一页面载体

@Component

自定义子组件

可多处复用,依赖父组件传参

@Param

组件入参

接收父组件数据,单向数据流

@Link

双向绑定参数

父子数据互通,一方修改双方同步

三、基础自定义组件封装

以通用自定义按钮为例,实现基础UI封装,支持文本、尺寸、颜色自定义。

// 自定义按钮组件 CustomButton.ets@Componentexport struct CustomButton {  // 接收父组件传入参数  @Param btnText: string = "默认按钮"  @Param btnWidth: string = "120vp"  @Param bgColor: ResourceColor = "#007DFF"  build() {    Button(this.btnText)      .width(this.btnWidth)      .backgroundColor(this.bgColor)      .fontColor(Color.White)      .borderRadius(8)  }}

3.1 页面引入使用

import { CustomButton } from './CustomButton'@Entry@Componentstruct Index {  build() {    Column({ space: 20 }) {      // 使用默认样式      CustomButton()      // 自定义参数      CustomButton({        btnText: "提交",        btnWidth: "160vp",        bgColor: "#1677ff"      })    }    .width('100%')    .padding(20)  }}

四、父子组件单向传参与事件回调

@Param 为单向数据流,父组件数据更新会同步到子组件;若需要子组件向父组件传递消息,可通过自定义回调函数实现。

4.1 带回调的子组件

@Componentexport struct ClickItem {  @Param content: string  // 定义回调方法  @Param itemClick: () => void  build() {    Text(this.content)      .fontSize(16)      .padding(12)      .backgroundColor("#f5f5f5")      .onClick(() => {        // 触发父组件回调        this.itemClick()      })  }}

4.2 父组件接收回调

import { ClickItem } from './ClickItem'@Entry@Componentstruct Index {  build() {    Column() {      ClickItem({        content: "点击我触发回调",        itemClick: () => {          console.log("子组件被点击,父组件收到通知")        }      })    }  }}

五、@Link 双向数据绑定实战

当需要父子组件数据双向同步时,使用 @Link 装饰器。父组件使用 $$ 语法传参,子组件修改数据会直接同步回父组件。

5.1 双向绑定子组件

@Componentexport struct InputItem {  // 双向绑定变量  @Link inputValue: string  build() {    TextInput({ text: this.inputValue })      .onChange((value: string) => {        // 子组件修改,自动同步父组件        this.inputValue = value      })      .width("240vp")      .height("40vp")  }}

5.2 父组件调用

import { InputItem } from './InputItem'@Entry@Componentstruct Index {  @State msg: string = ""  build() {    Column({ space: 15 }) {      // $$ 标记双向绑定      InputItem({ inputValue: $$this.msg })      Text(`父组件内容:${this.msg}`).fontSize(16)    }    .padding(20)  }}

六、公共样式抽离与全局管理

将颜色、尺寸、圆角、字体等通用样式抽离为独立文件,统一管控,实现一键换肤、全局样式统一。

6.1 新建全局样式文件 style.ets

// 全局样式常量export const StyleConfig = {  // 主色调  primaryColor: "#007DFF",  // 辅助色  assistColor: "#666666",  // 圆角  radius: 8,  // 通用字体大小  fontNormal: 14,  fontLarge: 18}

6.2 组件引入全局样式

import { StyleConfig } from './style'@Componentexport struct CardView {  build() {    Column() {      Text("通用卡片")        .fontSize(StyleConfig.fontNormal)        .fontColor(StyleConfig.assistColor)    }    .width("100%")    .padding(15)    .borderRadius(StyleConfig.radius)    .backgroundColor("#ffffff")  }}

七、组件渲染优化与高频坑点

  • 滥用@State:非动态数据不要用状态装饰器,避免无效重渲染;

  • @Param 直接修改:单向参数禁止在子组件内赋值,会触发报错,修改数据请用回调;

  • @Link 传参错误:父组件必须使用 $$,否则双向绑定失效;

  • 样式硬编码:大量重复样式不抽离,后期维护、换肤成本极高;

  • 组件拆分过细/过粗:合理拆分,单一职责原则,一个组件只做一件事。

八、全文总结

组件化是鸿蒙工程化开发的核心能力,合理封装通用组件,能够大幅减少重复代码、统一App UI风格、降低维护难度。

区分好 @Param 单向传参、@Link 双向绑定、事件回调的使用场景,配合全局样式抽离,就能搭建一套稳定、易扩展的组件库。本文所有代码均可直接在项目中运行,适配 API 10 及以上版本。

最新文章

随机文章