uni-app的UTS插件开发,调用鸿蒙原生API
随着uni-app对鸿蒙系统的支持不断增强,开发者可以通过UTS(Uni Typed Script)插件实现鸿蒙原生组件的嵌入与交互。从HBuilderX 4.62版本开始,uni-app提供了对鸿蒙原生组件的同层渲染支持,开发者可以直接在
.ets
文件中定义原生组件,并通过UTS插件将其集成到uni-app项目中。本文将以「自定义按钮组件」为例,详细讲解如何在鸿蒙系统中注册原生组件,并在uni-app中调用它。
1. UTS插件编写关键步骤和注意事项
1.1 创建插件目录
首先,需要在项目中创建一个 uni_modules
目录。如果项目中已经存在该目录,则跳过此步骤。然后,在 uni_modules
目录下新建一个 UTS 插件,选择 API 插件类型,并设置插件ID。例如,创建一个名为 unique-id
的插件:
- 在项目根目录下创建
uni_modules
目录(如果已存在则跳过)。 - 在
uni_modules
目录下新建一个名为unique-id
的文件夹。 - 在
unique-id
文件夹下创建utssdk
目录,这是插件代码功能部分。 - 根据需要创建
readme
文件,用于说明插件的功能和使用方法。 - 如果需要支持其他平台,可以创建
app-android
和app-ios
目录。 - 在
utssdk
目录下创建interface.uts
文件,用于声明插件的接口。 - 在
utssdk
目录下创建config.json
文件,用于配置原生层的相关信息。
1.2 插件目录结构
一个典型的UTS插件目录结构如下:
uni_modules/unique-id/
├── utssdk/
│ ├── interface.uts // 接口声明文件
│ ├── config.json // 原生层配置文件
│ └── app-harmony/ // 鸿蒙端实现代码目录
│ ├── index.uts // 鸿蒙端的具体实现文件
│ ├── resources/ // 资源文件目录(图片、字体等)
│ └── module.json5 // 模块配置文件
├── app-android/ // Android端实现代码目录(可选)
├── app-ios/ // iOS端实现代码目录(可选)
└── readme.md // 说明文件
1.3 编写插件代码
UTS插件使用TypeScript编写,支持跨平台编译。例如,在Web平台上编译为JavaScript,在Android平台上编译为Kotlin,在iOS平台上编译为Swift。UTS插件的语法与TypeScript基本一致,支持大部分ES6 API。
例如,编写一个简单的UTS插件来获取设备ID:
// utssdk/index.uts
export function getDeviceId(): string {const context = plus.android.runtimeMainActivity();const ContentResolver = plus.android.importClass('android.content.ContentResolver');const SettingsSecure = plus.android.importClass('android.provider.Settings$Secure');const deviceId = SettingsSecure.getString(context.getContentResolver(), SettingsSecure.ANDROID_ID);return deviceId;
}
1.4 原生模块对接
对于需要调用原生模块的场景,需要在相应平台上实现原生模块的对接。例如,在Android端实现原生模块的封装和调用。
在鸿蒙端,我们可以直接在 .ets
文件中定义原生组件,并通过 UTS 插件将其集成到 uni-app 项目中。例如,定义一个自定义按钮组件:
// utssdk/app-harmony/HarmonyButton.ets
@Component
struct HarmonyButton {@Builder option: { label: string, onClick: () => void }build() {Column() {Button() {Text(this.option.label).fontSize(16)}.onClick(() => {this.option.onClick();}).width("100%").height(50)}}
}
然后在 utssdk/app-harmony/index.uts
中注册该组件:
// utssdk/app-harmony/index.uts
import { HarmonyButton } from './HarmonyButton';defineNativeEmbed({tag: 'harmony-button',builder: (options: { label: string, onClick: () => void }) => {return new HarmonyButton(options);}
});
1.5 插件引用方式
插件可以在前端通过两种方式引用:泛型引用和显性引用。
- 泛型引用:将整个插件作为一个对象导入,适合需要使用多个功能的场景。
- 显性引用:只导入需要的特定方法或属性,可以减少代码体积,提高运行效率。
例如,在页面中使用显性引用方式调用 getDeviceId
方法:
<script>
import { getDeviceId } from '@/uni_modules/unique-id';export default {methods: {async fetchDeviceId() {const deviceId = await getDeviceId();console.log('Device ID:', deviceId);}},mounted() {this.fetchDeviceId();}
};
</script>
1.6 发布插件市场
当插件开发完成后,可以通过HBuilderX发布到插件市场,供其他开发者使用。具体步骤如下:
- 在HBuilderX中打开你的插件项目。
- 点击菜单栏「插件管理」→「发布插件」。
- 按照提示填写插件的相关信息,并上传必要的文件。
- 提交发布申请,等待审核通过。
2. 原生组件注册流程
2.1 使用 defineNativeEmbed
注册组件
defineNativeEmbed
是uni-app提供的用于注册原生组件的函数。它允许我们指定组件的标签名 tag
和构建函数 builder
。构建函数接收参数并返回鸿蒙原生组件实例。例如:
// utssdk/app-harmony/index.uts
import { HarmonyButton } from './HarmonyButton';defineNativeEmbed({tag: 'harmony-button',builder: (options: { label: string, onClick: () => void }) => {return new HarmonyButton(options);}
});
2.2 使用 @Component
和 @Builder
装饰器定义组件
在鸿蒙的.ets
文件中,我们可以使用 @Component
和 @Builder
装饰器来定义原生组件的结构和逻辑。例如:
// utssdk/app-harmony/HarmonyButton.ets
@Component
struct HarmonyButton {@Builder option: { label: string, onClick: () => void }build() {Column() {Button() {Text(this.option.label).fontSize(16)}.onClick(() => {this.option.onClick();}).width("100%").height(50)}}
}
3. 事件传递机制
3.1 原生组件的事件注册
在鸿蒙的原生组件中,我们可以使用 .onClick
来注册点击事件。例如,上述 HarmonyButton
组件中通过 .onClick
来注册点击事件。
3.2 在 uni-app 页面中监听事件
在 uni-app 的页面中,我们可以像使用普通组件一样,通过 @click
来监听事件,并接收事件对象。例如:
<template><view><harmony-button:label="buttonLabel"@click="handleButtonClick"/></view>
</template><script>
export default {data() {return {buttonLabel: '点击我'};},methods: {handleButtonClick() {console.log('按钮被点击了');this.buttonLabel = '已点击';}}
};
</script>
4. 动态属性更新
4.1 修改 options
对象的值
修改 options
对象的值(如 label
)会触发组件的更新。为了确保 options
是响应式数据,通常需要将它定义为 Vue 的 data
属性。例如:
<template><view><harmony-button:label="dynamicLabel"@click="updateLabel"/></view>
</template><script>
export default {data() {return {dynamicLabel: '初始文本'};},methods: {updateLabel() {this.dynamicLabel = '更新后的文本';}}
};
</script>
5. 运行与调试
5.1 HBuilderX 配置
确保你已经安装了 HBuilderX 4.62+ 版本。然后在菜单栏选择「运行」→「运行到手机或模拟器」→「运行到鸿蒙」。在调试之前,请确保你的设备已开启「开发者选项」和「USB 调试」。
5.2 DevEco Studio 验证
通过 DevEco Studio 查看日志输出,确认组件是否成功加载。检查按钮点击事件是否触发并更新标签文本。
6. 注意事项
6.1 ETS 文件限制
鸿蒙原生组件仅支持定义在 .ets
文件中。UTS 插件需要通过 import
引入 .ets
文件。
6.2 权限声明
在 config.json
中添加必要的权限。例如,如果需要定位权限,可以这样写:
{"module": {"requestPermissions": [{"name": "ohos.permission.LOCATION","usedScene": {"when": "inuse"},"reason": "$string:permission_location_reason"}]}
}
6.3 context 获取
很多鸿蒙原生 API 需要 context
作为参数。在大多数情况下,直接使用 getContext()
即可获取到上下文对象。例如:
import settings from '@ohos.settings';const context: Context = getContext();
settings.getValue(context, settings.display.SCREEN_BRIGHTNESS_STATUS, (err, value) => {if (err) {console.error(`Failed to get the setting. ${err.message}`);return;}console.log(`SCREEN_BRIGHTNESS_STATUS: ${JSON.stringify(value)}`);
});
7. 编写步骤详解
7.1 第一步:定义插件接口(interface.uts
)
目的: 明确插件对外暴露的 API 规范,方便多端实现和 IDE 智能提示。这是 UTS 插件开发的基础,所有端的实现都需要遵循这里定义的接口。
操作: 在 uni_modules/你的插件名/utssdk/
下新建或编辑 interface.uts
文件,定义你要暴露的类型和方法签名。例如:
// uni_modules/your-plugin-name/utssdk/interface.uts
export type MyApiSync1 = (paramA: string) => string;
7.2 第二步:鸿蒙端实现接口(app-harmony/index.uts
)
目的: 按照接口定义,实现鸿蒙端的具体逻辑。
操作: 在 uni_modules/你的插件名/utssdk/app-harmony/
下新建或编辑 index.uts
文件,实现方法。例如:
// uni_modules/your-plugin-name/utssdk/app-harmony/index.uts
import { MyApiSync1 } from '../interface.uts';
import { promptAction } from '@ohos.prompt';interface ShowToastOptions {message: string;
}export const myApiSync1: MyApiSync1 = function (paramA: string): string {let options: ShowToastOptions = { message: paramA };promptAction.showToast(options);return paramA;
}
7.3 第三步:在页面中调用插件方法
目的: 验证插件功能是否生效,体验 UTS 跨端调用的便捷性。
操作: 在页面脚本中引入并调用插件方法。例如:
<template><view><button @click="showToast">显示鸿蒙 Toast</button></view>
</template><script>
import { myApiSync1 } from '@/uni_modules/your-plugin-name';export default {methods: {showToast() {const msg = 'Hello Harmony!';const result = myApiSync1(msg);console.log(result); // 输出: Hello Harmony!}}
}
</script>
8. UTS 插件的兼容性与配置
8.1 兼容性
- HBuilderX 4.27+ 开始支持 Harmony Next 平台的 App 开发。
- HBuilderX 4.24+ 开始支持运行到鸿蒙平台。
- 鸿蒙开发仅支持 Vue3,不支持 Vue2。
- 不支持
plus
,但支持nvue
。 - HBuilderX 4.41+ 开始运行到鸿蒙设备时支持修改代码后热刷更新。
- HBuilderX 4.61+ 开始支持 uni-app x 项目,且支持开启调试功能。
- HBuilderX 4.71+ 开始支持 uni-app x 项目运行到 x86_64 平台的鸿蒙模拟器。
8.2 配置依赖
鸿蒙的库管理工具是 ohpm,类似于 js 的 npm 和 Android 的 aar。鸿蒙的三方 SDK 封装文件为 .har
文件。在 utssdk/app-harmony/config.json
文件内可以配置依赖,使用鸿蒙的三方库,配置方式如下:
{"dependencies": {"@cashier_alipay/cashiersdk": "15.8.26", // ohpm依赖"local-deps": "./libs/local-deps.har" // 本地依赖}
}
注意: config.json
文件不能含注释,本地依赖相对路径是相对于 config.json
文件所在目录的路径。
8.3 resources 目录
UTS 插件内包含了一个 resources
目录,用于存放插件的资源文件,如图片、字体等。此目录位于 utssdk/app-harmony/resources
。
8.4 module.json5
开发者可以在 UTS 插件内配置 module.json5
文件,用于配置插件的一些信息,如模块名、支持的设备类型、请求的权限等。配置权限请参考鸿蒙官方文档:声明权限。例如:
{"module": {"name": "uni_modules__test_mylocation", // 鸿蒙模块名,默认值生成规则见下文"type": "har", // 固定为har"deviceTypes": ["default","tablet","2in1"],"requestPermissions": [{"name": "ohos.permission.LOCATION","usedScene": {"when": "inuse"},"reason": "$string:permission_location_reason" // 本地resources内的字符串}]}
}
鸿蒙模块名生成规则:
- 对于一个名称为
uni-getBatteryInfo
的 uni_module,其moduleName
为uni_modules__uni_getbatteryinfo
,packageName
为@uni_modules/uni-getbatteryinfo
。 packageName
(引用模块名)规则为给 uni_module 名称前加上@uni_modules
前缀然后转为全小写。moduleName
(鸿蒙模块名)是在packageName
的基础上生成的,移除@
符号,将/
替换为两个下划线,将-
替换为一个下划线。
9. 总结
通过 UTS 插件和鸿蒙原生组件的结合,开发者可以在 uni-app 中高效地扩展鸿蒙平台的能力。UTS 插件其实就是 uni-app x 扩展 API 的标准插件形式,你可以把它理解成“写一份 TypeScript 风格的代码,编译后在不同平台都能用”。编写 UTS 插件时,只需记住:UTS 写的代码,最终会被编译成 ArkTS(.ets)文件,然后就能愉快地调用鸿蒙的原生 API 了。
希望本文能够帮助开发者更好地理解和掌握在 uni-app 中使用 UTS 插件来嵌入鸿蒙原生组件的方法。如果你有任何问题或需要进一步的帮助,欢迎访问 官方文档 或社区论坛寻求支持。
其他参考
https://doc.dcloud.net.cn/uni-app-x/plugin/uts-for-harmony.html
https://uniapp.dcloud.net.cn/tutorial/harmony/intro.html