UTS插件仅支持App端(iOS/Android),需HBuilderX 3.99+或CLI 4.20+,且须开启"uts":true、文件置于uts/目录、小写下划线命名、相对路径导入;调用原生API需通过plus/uni对象,禁用new原生类,异步用await,UI操作须主线程执行。

UTS 插件不能直接在 H5 或小程序平台运行,仅支持 App(iOS/Android)端,且必须用 3.99+ 版本的 HBuilderX 或 CLI 4.20+ 编译才可生效。
UTS 插件为什么编译不进 App?
常见现象是:写了 uts 文件、配置了 nativePlugins,但真机调试时完全没调用、无日志、也无报错。根本原因通常是以下之一:
- 项目未开启「UTS 编译支持」:HBuilderX 中需在
manifest.json → 源码视图手动添加"uts": true;CLI 用户需确认vue.config.js中已启用uni-app的 UTS 构建插件 - UTS 文件路径不在
uts/目录下(注意不是uni_modules/或nativePlugins/),且文件名必须全小写 + 下划线命名(如my_util.uts) - 调用时用了错误的模块路径:UTS 模块导入必须用相对路径,且不带扩展名,例如
import myUtil from '@/uts/my_util',不能写成import { xxx } from 'my_util' - Android 端未在
android/app/src/main/AndroidManifest.xml中声明所需权限(如摄像头、定位),或 iOS 端未在ios/manifest.json补充NSCameraUsageDescription等描述字段
如何在 UTS 里安全调用原生 API?
UTS 不是“写 Java/Kotlin/Objective-C”,而是通过预置的 plus 和 uni 对象桥接原生能力,本质仍是 uni-app 的运行时封装。关键约束如下:
-
plus.runtime、plus.device等对象在 UTS 中可用,但部分方法返回值类型与 JS 层不同(例如plus.runtime.getProperty()在 UTS 中返回Map<String, Any>,而非 JS Object),需显式解构 - 不能直接 new Android/iOS 原生类(如
new Intent()),必须走uni.requireNativePlugin('xxx')加载已注册的原生插件,或使用plus.android.importClass()/plus.ios.importClass()动态导入(仅限 App 端) - 异步操作必须用
await+Promise封装,UTS 不支持回调函数传参方式;例如调用相机需用await plus.camera.getCamera().captureImage(),而非传 success/fail 回调 - 涉及 UI 操作(如弹 Toast、跳原生页面)必须在主线程执行:
plus.android.runOnMainThread(() => { ... }),否则 Android 上会 crash
UTS 和原生插件(uni_modules/nativePlugins)怎么选?
二者定位不同,混用时容易混淆职责:
- UTS 适合轻量逻辑封装:比如加解密、时间格式化、本地 SQLite 查询、蓝牙设备扫描过滤等「纯逻辑 + 少量原生调用」场景;代码可跨平台(iOS/Android 共用一份
.uts) - 原生插件(
nativePlugins)适合重度原生交互:如自定义 View、音视频硬编解码、AR 渲染、后台保活服务等,需分别写 Kotlin/Swift,并通过UniModule注册暴露给 JS - UTS 可以调用已注册的原生插件(
uni.requireNativePlugin('myPlugin')),但原生插件无法反向调用 UTS —— UTS 不是运行时模块,编译后就固化为字节码 - 性能上,UTS 调用比 JS → 原生插件多一层桥接,但差距微乎其微;真正瓶颈通常在原生层,而非桥接本身
UTS 最容易被忽略的是生命周期绑定:它没有 onLoad 或 onShow 这类钩子,所有初始化逻辑必须显式触发(比如在页面 onReady 里调用 UTS 初始化函数),且不能依赖 Vue 实例上下文 —— 它和页面是解耦的。


















