在uni-app跨平台开发中,当需要调用鸿蒙系统特有的原生能力(如读取设备信息、打开应用市场详情页)时,UTS插件是关键桥梁。UTS(uni-app TypeScript)允许你在uni-app项目中用TypeScript直接调用鸿蒙ArkTS API,省去了JS桥接开销,性能更优。本文以跳转华为应用市场详情页为例,完整演示从创建到调用的技术细节,并总结踩坑经验。
一、新建uni_modules插件
在项目根目录的 'uni_modules' 文件夹(如不存在则新建)内,右键选择“新建uni_modules插件”。插件命名建议用英文,例如 'openAppProduct';注意避免以 'uni-' 开头(官方插件保留前缀),个人插件推荐用开发者标识开头,如 'wq-openAppProduct'。
二、配置package.json声明ArkTS支持
编辑插件根目录的 package.json,在 'uni_modules' 节点下新增 'uni-ext-api' 配置,声明该插件支持鸿蒙ArkTS平台(arkts: true),其他平台对应设为false:- {
- "uni_modules": {
- "uni-ext-api": {
- "uni": {
- "openAppProduct": {
- "name": "openAppProduct",
- "app": {
- "js": false,
- "kotlin": false,
- "swift": false,
- "arkts": true
- }
- }
- }
- }
- }
- }
复制代码
三、定义接口类型(interface.uts)
编写 'utssdk/interface.uts' 文件,定义对外暴露的参数类型和回调风格。uni-app规范使用 success/fail/complete 回调:- export interface Uni {
- openAppProduct(options: OpenAppProductOptions): void;
- }
- export type OpenAppProduct = (options: OpenAppProductOptions) => void;
- export type OpenAppProductSuccess = { errMsg: string };
- export type OpenAppProductSuccessCallback = (result: OpenAppProductSuccess) => void;
- export type OpenAppProductFail = { errMsg: string };
- export type OpenAppProductFailCallback = (result: OpenAppProductFail) => void;
- export type OpenAppProductComplete = { errMsg: string };
- export type OpenAppProductCompleteCallback = (result: OpenAppProductComplete) => void;
- export type OpenAppProductOptions = {
- success?: OpenAppProductSuccessCallback | null,
- fail?: OpenAppProductFailCallback | null,
- complete?: OpenAppProductCompleteCallback | null
- };
复制代码
四、实现鸿蒙原生代码(app-harmony/index.uts)
编写 'utssdk/app-harmony/index.uts' 文件,调用两个关键鸿蒙API:bundleManager.getBundleInfoForSelfSync 获取当前应用包名,productViewManager.loadProduct 打开应用市场详情页。注意:productViewManager.loadProduct 本身没有成功回调,只有 error 回调,因此代码通过 isSuccess 标志做“反向判断”。- import { OpenAppProduct, OpenAppProductOptions, OpenAppProductSuccess, OpenAppProductFail, OpenAppProductComplete } from '../interface.uts';
- import bundleManager from '@ohos.bundle.bundleManager';
- export { OpenAppProduct, OpenAppProductOptions, OpenAppProductSuccess, OpenAppProductFail, OpenAppProductComplete };
- import { productViewManager } from '@kit.StoreKit';
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import type { common, Want } from '@kit.AbilityKit';
- import { BusinessError } from '@kit.BasicServicesKit';
- export function openAppProduct(options: OpenAppProductOptions) {
- let isSuccess = true;
- try {
- const request: Want = {
- parameters: {
- bundleName: bundleManager.getBundleInfoForSelfSync(
- bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT
- ).name
- }
- };
- productViewManager.loadProduct(
- getContext() as common.UIAbilityContext,
- request,
- {
- onError: (err: BusinessError) => {
- isSuccess = false;
- hilog.info(0, 'TAG', `loadProduct onError. code is ${err.code}, message is ${err.message}`);
- let result: OpenAppProductFail = { errMsg: err.message ?? "" };
- const completeResult: OpenAppProductComplete = { errMsg: err.message ?? "" };
- options?.fail?.(result);
- options?.complete?.(completeResult);
- }
- } as productViewManager.ProductViewCallback
- );
- } catch (err) {
- isSuccess = false;
- hilog.error(0, 'TAG', `loadProduct failed. code is ${err.code}, message is ${err.message}`);
- let result: OpenAppProductFail = { errMsg: err.message ?? "" };
- const completeResult: OpenAppProductComplete = { errMsg: err.message ?? "" };
- options?.fail?.(result);
- options?.complete?.(completeResult);
- }
- if (isSuccess) {
- let result: OpenAppProductSuccess = { errMsg: "ok" };
- const completeResult: OpenAppProductComplete = { errMsg: "ok" };
- options?.success?.(result);
- options?.complete?.(completeResult);
- }
- }
复制代码
五、在页面中使用插件
方式一:挂载到 uni 全局对象。在任意页面引入一次(避免被Tree Shaking摇掉),然后直接调用 uni.openAppProduct()。- <template>
- <view class="content">
- <button class="button" @click="openAppProductBtn">打开应用市场</button>
- </view>
- </template>
- <script lang="uts">
- // 注意:需要在任意页面引入 1 次,否则可能被摇掉
- // import "@/uni_modules/xxx-openAppProduct"
- export default {
- methods: {
- openAppProductBtn() {
- uni.openAppProduct({
- success: (res) => { console.log('success: ', JSON.stringify(res)); },
- fail: (err) => { console.error('fail: ', JSON.stringify(err)); },
- complete: (res) => { console.log('complete: ', JSON.stringify(res)); }
- });
- }
- }
- }
- </script>
复制代码 方式二:直接 import 函数调用,这种方式对Tree Shaking更友好。- <template>
- <view class="content">
- <button class="button" @click="openAppProductBtn">打开应用市场</button>
- </view>
- </template>
- <script lang="uts">
- import { openAppProduct } from "@/uni_modules/xxx-openAppProduct"
- export default {
- methods: {
- openAppProductBtn() {
- openAppProduct({
- success: (res: any) => { console.log('success: ', JSON.stringify(res)); },
- fail: (err: any) => { console.error('fail: ', JSON.stringify(err)); },
- complete: (res: any) => { console.log('complete: ', JSON.stringify(res)); }
- });
- }
- }
- }
- </script>
复制代码
六、运行到鸿蒙设备
在HBuilderX顶部菜单选择“运行 → 运行到手机或模拟器 → 运行到鸿蒙”。新安装的HBuilderX需先点击“下载真机运行插件”安装运行环境。运行后DevEco Studio自动启动并编译部署。
七、调用鸿蒙第三方ohpm库
在UTS插件中也可以调用鸿蒙的ohpm三方库(如支付宝SDK、推送SDK)。安装ohpm包后,在 'utssdk/app-harmony/*.uts' 文件中import使用。注意:ohpm库不能直接在页面的 'pages/*.vue' 中import,必须通过UTS插件封装。示例:
页面中调用:- import { requestPayment } from "@/uni_modules/test-alipay";
- requestPayment({ orderInfo: "xxxx" });
复制代码 插件实现 'utssdk/app-harmony/index.uts':- import { Pay } from '@cashier_alipay/cashiersdk';
- export interface RequestPaymentOptions { orderInfo: string }
- export function requestPayment(options: RequestPaymentOptions) {
- return new Pay().pay(options.orderInfo, true);
- }
复制代码
八、UTS插件架构概览
项目目录结构:- 项目根目录/
- ├── pages/index/index.vue # 调用方
- ├── uni_modules/xxx-openAppProduct/ # UTS插件
- │ ├── package.json # 配置 arkts: true
- │ └── utssdk/
- │ ├── interface.uts # 类型定义(跨平台通用)
- │ └── app-harmony/index.uts # 鸿蒙原生实现
- │ # 还可添加 app-android/、app-ios/ 等平台目录
复制代码
九、踩坑记录与注意事项
1. 插件名不要以 uni- 开头,避免与官方插件冲突。
2. interface.uts 中定义的类型,在 app-harmony/index.uts 中必须用相对路径 '../interface.uts' 引入。
3. 挂载到 uni 全局对象的插件,需在任意页面 import 一次,否则可能被Tree Shaking摇掉;使用import函数方式则无需此操作。
4. productViewManager.loadProduct 没有成功回调,只能通过 isSuccess 标志“反向判断”——未进入 error 回调即视为成功。这是鸿蒙 API 的设计局限。
5. 第三方ohpm库只能在UTS插件文件中调用,不能在页面 script 中直接import。
6. 真机运行需先安装“真机运行插件”(HBuilderX提示后点击下载),运行会联动 DevEco Studio。
通过以上步骤,你可以在uni-app鸿蒙项目中高效封装UTS插件,调用原生API或第三方库,实现跨平台原生能力复用。 |