随着 uni-app 对鸿蒙系统的支持不断增强,开发者可以通过 UTS 插件 实现鸿蒙原生组件的嵌入与交互。从 HBuilderX 4.62 版本开始,uni-app 提供了对鸿蒙原生组件的同层渲染支持,开发者可以直接在 .ets 文件中定义原生组件,并通过 UTS 插件将其集成到 uni-app 项目中。
本文将以「自定义按钮组件」为例,详细讲解如何在鸿蒙系统中注册原生组件,并在 uni-app 中调用它。
开发步骤详解
1. 创建 UTS 插件结构
目录结构
uni_modules/
  └── wq-button-component/  ← 插件主目录
      ├── package.json      ← 插件配置文件
      ├── utssdk/
      │   ├── interface.uts   ← 接口定义
      │   └── app-harmony/
      │       └── index.uts   ← 鸿蒙实现(ETS 文件)
      └── pages/
          └── demo.vue      ← 演示页面配置 package.json
{
  "uni_modules": {
    "uni-ext-api": {
      "uni": {
        "customButton": {
          "name": "customButton",
          "app": {
            "js": false,
            "arkts": true
          }
        }
      }
    }
  }
}2. 在 ETS 文件中注册原生组件
ETS 实现代码
// uni_modules/wq-button-component/utssdk/app-harmony/index.ets
import { NativeEmbedBuilderOptions, defineNativeEmbed } from "@dcloudio/uni-app-runtime";
// 定义按钮组件的 BuilderOptions
interface ButtonBuilderOptions extends NativeEmbedBuilderOptions {
  label: string;
}
// 定义点击事件的详细信息
interface ButtonClickEventDetail {
  text: string;
}
// 原生按钮组件
@Component
struct ButtonComponent {
  @Prop label: string;
  onButtonClick?: Function;
  build() {
    Button(this.label)
      .width('100%')
      .height('100%')
      .onClick(() => {
        if (this.onButtonClick) {
          const detail: ButtonClickEventDetail = {
            text: 'test'
          };
          this.onButtonClick({ detail });
        }
      });
  }
}
// 构造函数,将参数传递给组件
@Builder
function ButtonBuilder(options: ButtonBuilderOptions) {
  ButtonComponent({
    label: options.label,
    onButtonClick: options?.on?.get('click')
  })
    .width(options.width)
    .height(options.height);
}
// 注册原生组件,标签名为 'button'
defineNativeEmbed('button', {
  builder: ButtonBuilder
});3. 在 uni-app 页面中调用组件
模板代码
<template>
  <view class="content">
    <embed 
      class="native-button" 
      tag="button" 
      :options="options" 
      @click="handleClick"
    ></embed>
  </view>
</template>
<script lang="uts">
export default {
  data() {
    return {
      options: {
        label: '点击我',
        width: 200,
        height: 50
      }
    };
  },
  methods: {
    handleClick(e) {
      console.log('按钮被点击,事件内容:', e.detail.text);
      this.options = {
        label: '已点击',
        width: 200,
        height: 50
      };
    }
  }
};
</script>
<style scoped>
.content {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
.native-button {
  width: 200px;
  height: 50px;
  margin: 10px auto;
}
</style>关键点解析
1. 原生组件注册流程
- 使用 defineNativeEmbed注册组件,指定标签名tag和构建函数builder。
- builder函数接收参数并返回鸿蒙原生组件实例。
- 通过 @Component和@Builder装饰器定义组件结构和逻辑。
2. 事件传递机制
- 原生组件的事件通过 on属性注册,例如onButtonClick。
- 在 uni-app页面中通过@click监听事件,并接收事件对象e.detail.text。
3. 动态属性更新
- 修改 options对象的值(如label)会触发组件更新。
- 需要确保 options是响应式数据(如 Vue 的data)。
运行与调试
1. HBuilderX 配置
- 安装 HBuilderX 4.62+。
- 在菜单栏选择 运行 → 运行到手机或模拟器 → 运行到鸿蒙。
- 确保设备已开启 开发者选项 和 USB 调试。
2. DevEco Studio 验证
- 查看日志输出,确认组件是否成功加载。
- 检查按钮点击事件是否触发并更新标签文本。
注意事项
- ETS 文件限制
- 鸿蒙原生组件仅支持定义在 .ets文件中。
- UTS 插件需通过 import引入.ets文件。
- 权限声明
在 config.json中添加必要权限:
{
  "plus": {
    "distribute": {
      "harmony": {
        "requestPermissions": [
          "ohos.permission.GET_BUNDLE_INFO"
        ]
      }
    }
  }
}- 上下文获取
- getContext()需确保在鸿蒙环境下可用。
- 可封装兼容性处理逻辑,避免空指针异常。
扩展思考
1. 复用组件模式
通过 @Reusable 装饰器实现组件复用,优化性能:
@Reusable
@Component
struct ReusableButton {
  // 组件逻辑
}2. 多类型组件注册
注册多个原生组件时,可使用不同标签名区分:
defineNativeEmbed('custom-button', { builder: CustomButtonBuilder });
defineNativeEmbed('custom-input', { builder: InputBuilder });总结
通过 UTS 插件和鸿蒙原生组件的结合,开发者可以在 uni-app 中高效地扩展鸿蒙平台的能力。本文以按钮组件为例,演示了从组件注册到页面调用的完整流程,帮助开发者快速掌握鸿蒙原生组件的嵌入技巧。










