9.1 UTS 语言核心设计理念
UTS(Uni Type Script)是 DCloud 专为 uni-app x 设计的编译型语言。它的核心设计目标是:让前端开发者用接近 TypeScript 的语法,直接调用原生平台的 API,并获得原生代码的性能。
UTS 与 TypeScript 的关键区别:
| 特性 | TypeScript | UTS |
|---|---|---|
| 运行时 | JS 引擎(V8/JSCore) | 原生运行时(ART/Swift) |
| 编译产物 | JavaScript | Kotlin / Swift / JS(按平台) |
| npm 生态 | 完整支持 | 不支持(需专门适配) |
| 原生 API 调用 | 通过 Bridge 间接调用 | 直接调用,零开销 |
| 类型系统 | 结构化类型(兼容) | 名义类型(更严格) |
| 语法兼容 | — | 90% 兼容 TypeScript 语法 |
9.2 UTS 语法详解
基础类型系统
UTS 的类型系统比 TypeScript 更接近强类型语言:
// 基本类型(与 TypeScript 一致)
let count: number = 42
let name: string = 'hello'
let active: boolean = true
let data: any = null // 谨慎使用 any
// 平台特有类型(Android 编译时有效)
let context: android.content.Context
let bitmap: android.graphics.Bitmap
// UTS 的可空类型(重要!)
let maybeNull: string | null = null
let result = maybeNull?.length // 可选链访问
let len = maybeNull ?? 0 // 空值合并
// 数组
const nums: number[] = [1, 2, 3]
const strs: Array<string> = ['a', 'b']
// 接口(与 TypeScript 一致)
interface Point {
x: number
y: number
label?: string
}
// 类(支持继承和接口实现)
class Circle {
radius: number
constructor(radius: number) {
this.radius = radius
}
area(): number {
return Math.PI * this.radius ** 2
}
}
UTS 的特殊语法
UTS 引入了一些 TypeScript 中没有的语法,用于与原生平台交互:
// as 类型转换(强制转换,类似 Kotlin 的 as)
const view = UTSAndroid.getContext().findViewByTag(100) as android.view.TextView
// instanceof 类型判断
if (view instanceof android.view.Button) {
// 在此作用域内,view 被自动推断为 Button 类型
view.setText("点击")
}
// 平台特有的 lambda/闭包语法(编译到 Kotlin 时)
// Android 原生 OnClickListener
view.setOnClickListener({
onClick(v: android.view.View) {
console.log('被点击了')
}
})
9.3 调用 Android 原生 API
这是 UTS 最强大的能力。通过直接 import Android SDK 的类,可以实现任何原生功能:
// uts-plugins/vibrate/index.uts
// 直接导入 Android 原生类
import Vibrator from 'android.os.Vibrator'
import VibrationEffect from 'android.os.VibrationEffect'
import Context from 'android.content.Context'
import Build from 'android.os.Build'
/**
* 自定义震动(时长和强度)
* @param duration 震动时长(毫秒)
* @param amplitude 震动强度(1-255,仅 Android 8.0+ 支持)
*/
export function vibrate(duration: number, amplitude: number = 128): void {
const context = UTSAndroid.getUniActivity()!
const vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= 26) {
// Android 8.0+ 支持设置震动强度
const effect = VibrationEffect.createOneShot(duration, amplitude)
vibrator.vibrate(effect)
} else {
// 旧版 API(deprecated)
vibrator.vibrate(duration)
}
}
/**
* 检查设备是否有震动马达
*/
export function hasVibrator(): boolean {
const context = UTSAndroid.getUniActivity()!
const vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
return vibrator.hasVibrator()
}
访问 Android Activity 和 Context
// UTSAndroid 是 uni-app x 提供的全局工具对象
// 获取 Activity(非空断言 ! 表示我们确定它不为 null)
const activity = UTSAndroid.getUniActivity()! // MainActivity 实例
const appContext = UTSAndroid.getAppContext()! // Application Context
// 在主线程执行(UI 操作必须在主线程)
UTSAndroid.runOnMainThread(() => {
// 修改 UI 的代码
})
// 在子线程执行(网络请求、IO 操作)
UTSAndroid.runOnUIThread(() => {
// 此处实际上会在后台线程运行
})
9.4 调用 iOS 原生 API
// uts-plugins/haptic/index.uts(iOS 触觉反馈)
import UIImpactFeedbackGenerator from 'UIKit'
type HapticStyle = 'light' | 'medium' | 'heavy'
export function hapticFeedback(style: HapticStyle = 'medium'): void {
let feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle
switch (style) {
case 'light':
feedbackStyle = .light
break
case 'heavy':
feedbackStyle = .heavy
break
default:
feedbackStyle = .medium
}
const generator = new UIImpactFeedbackGenerator(style: feedbackStyle)
generator.prepare()
generator.impactOccurred()
}
// iOS 剪贴板操作
import UIPasteboard from 'UIKit'
export function copyToClipboard(text: string): void {
UIPasteboard.general.string = text
}
export function getClipboardContent(): string | null {
return UIPasteboard.general.string
}
9.5 UTS 插件结构
UTS 插件是 uni-app x 的插件单元,遵循特定的目录结构:
uni_modules/
└── my-vibrate/ # 插件名
├── package.json # 插件配置
├── readme.md
└── utssdk/
├── index.uts # 所有平台通用逻辑(可选)
├── app-android/
│ ├── index.uts # Android 专属逻辑
│ └── config.json # Android 依赖配置
└── app-ios/
├── index.uts # iOS 专属逻辑
└── config.json # iOS 依赖配置
// app-android/config.json — Android 配置
{
"minSdkVersion": 21,
"dependencies": [
// Gradle 依赖(如需要第三方 SDK)
"com.google.android.gms:play-services-location:21.0.1"
],
"abis": ["armeabi-v7a", "arm64-v8a"]
}
9.6 uvue 组件详解
uvue 是 uni-app x 的页面/组件文件格式,类似 .vue 但有一些重要差异:
<!-- pages/home/home.uvue -->
<template>
<!-- 使用原生组件,不同于 .vue 文件 -->
<list-view <!-- 高性能原生列表组件 -->
:data-source="list"
@load-more="loadMore"
>
<template #item="{ item }">
<product-item :data="item" />
</template>
</list-view>
</template>
<script lang="uts">
// uvue 的 script 使用 UTS 语言
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const list = ref<Product[]>([])
async function loadMore() {
// 这里可以直接调用 UTS 原生 API
const data = await fetchProducts()
list.value.push(...data)
}
return { list, loadMore }
}
})
</script>
<style>
/* uvue 支持 rpx 单位(这是与 nvue 的重要区别)*/
.container {
flex: 1;
background-color: #f5f5f0;
padding: 24rpx;
}
</style>
9.7 跨端能力封装模式
最佳实践:将平台相关的原生调用封装为跨端 API,让业务代码保持一致:
// uni_modules/my-haptic/utssdk/index.uts(跨平台通用接口)
export type HapticType = 'light' | 'medium' | 'heavy'
// #ifdef APP-ANDROID
import { vibrateAndroid } from './app-android/index.uts'
export function haptic(type: HapticType): void {
vibrateAndroid(type)
}
// #endif
// #ifdef APP-IOS
import { hapticIOS } from './app-ios/index.uts'
export function haptic(type: HapticType): void {
hapticIOS(type)
}
// #endif
// #ifndef APP
// H5 和小程序端 fallback
export function haptic(type: HapticType): void {
uni.vibrateShort({ type })
}
// #endif
// 业务代码无需关心平台差异
import { haptic } from '@/uni_modules/my-haptic'
haptic('medium') // 自动调用对应平台的实现
9.8 小结
- UTS 与 TypeScript 语法 90% 兼容,但本质是编译型语言,编译为 Kotlin/Swift/JS
- 通过
import直接导入 Android SDK / iOS SDK 的类,零桥接调用原生 API UTSAndroid.getUniActivity()和UTSAndroid.getAppContext()是 Android 端的核心工具- UTS 插件遵循
uni_modules/插件名/utssdk/目录结构,分平台实现 - uvue 文件中
<script lang="uts">使用 UTS 语言,支持 rpx 单位和更丰富的 CSS list-view(uni-app x 内置)是比 scroll-view 更高效的原生列表组件