HarmonyOS 是华为的分布式操作系统,应用默认使用 ArkTS 语言开发,基于 Stage 模型。
来源:华为 HarmonyOS 开发者文档(2026-04-23 访问)
- 文档中心: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides
- ArkTS 语言: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/introduction-to-arkts
- ArkUI 框架: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-basic-syntax-overview
- Stage 模型: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-configuration-file-stage
- 资源管理: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access
更新频率:随 HarmonyOS 版本迭代(当前覆盖 5.0~6.1)
ArkTS 在 TS 基础上做了以下限制:
let x: number = null 编译错误,需声明为 number | null类型说明使用场景HAPHarmonyOS Ability Package应用主包,可安装HARHarmonyOS Archive静态共享库,编译时打包HSPHarmonyOS Shared Package动态共享库,运行时共享
text
resources/
├── base/
│ ├── element/ # 字符串、颜色、尺寸等元素资源
│ ├── media/ # 图片、音视频等媒体资源
│ └── profile/ # 自定义配置文件
├── zh_CN/ # 限定词目录(语言_地区-横竖屏-设备类型-颜色模式-屏幕密度)
├── dark/ # 深色模式
└── rawfile/ # 原始文件,不编译
资源访问: $r('app.type.name') 或 $rawfile('path/file.png')
系统资源: $r('sys.type.name')
.ets 文件,用 @Component + build() 声明 UImodule.json5 中注册 UIAbility/EntryAbilityresources/ 下按限定词组织资源文件typescript
// Model
interface User {
id: number;
name: string;
email: string;
}
// ViewModel(使用 TaskPool 进行网络请求)
import { taskpool } from '@kit.ArkTS';
@Concurrent
async function fetchUsersFromServer(): Promise<User[]> {
// 模拟网络请求
const response = await http.createHttp();
const result = await response.request('https://api.example.com/users');
return JSON.parse(result.result as string) as User[];
}
// ViewModel
class UserListViewModel {
@State users: User[] = [];
@State isLoading: boolean = false;
@State error: string = '';
async loadUsers() {
this.isLoading = true;
this.error = '';
try {
const task = new taskpool.Task(fetchUsersFromServer);
this.users = await taskpool.execute(task) as User[];
} catch (e) {
this.error = (e as Error).message;
} finally {
this.isLoading = false;
}
}
}
// View
@Entry
@Component
struct UserListPage {
@State viewModel: UserListViewModel = new UserListViewModel();
build() {
Column() {
// 标题栏
Row() {
Text('用户列表')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Blank()
if (this.viewModel.isLoading) {
ProgressView()
.width(24)
.height(24)
}
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
// 错误提示
if (this.viewModel.error) {
Text(`错误: ${this.viewModel.error}`)
.fontColor(Color.Red)
.fontSize(14)
.padding(16)
}
// 用户列表
List({ space: 10 }) {
ForEach(this.viewModel.users, (user: User) => {
ListItem() {
this.UserItem(user)
}
.swipeAction({ end: this.DeleteAction(user.id) })
}, (user: User) => user.id.toString())
}
.width('100%')
.layoutWeight(1)
.padding(16)
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.onAppear(() => {
this.viewModel.loadUsers();
})
}
@Builder
UserItem(user: User) {
Row({ space: 12 }) {
Column() {
Text(user.name)
.fontSize(17)
.fontWeight(FontWeight.Medium)
Text(user.email)
.fontSize(14)
.fontColor('#666666')
}
.alignItems(HorizontalAlign.Start)
Blank()
Text(`#${user.id}`)
.fontSize(12)
.fontColor('#999999')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
}
@Builder
DeleteAction(id: number) {
Button('删除')
.type(ButtonType.Normal)
.height('100%')
..width(80)
.backgroundColor(Color.Red)
.onClick(() => {
// 删除逻辑
const index = this.viewModel.users.findIndex(u => u.id === id);
if (index >= 0) {
this.viewModel.users.splice(index, 1);
}
})
}
}
json
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": ["phone", "tablet"],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
}
]
}
}
json
{
"string": [
{
"name": "module_desc",
"value": "用户列表演示应用"
},
{
"name": "EntryAbility_desc",
"value": "主入口Ability"
},
{
"name": "EntryAbility_label",
"value": "用户列表"
}
]
}
text
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ View │ ←── │ ViewModel │ ←── │ Model │
│ (@Component)│ │ (@State/@Link)│ │ (interface) │
└─────────────┘ └──────────────┘ └─────────────┘
build() @State 数据结构
@Builder @Link 函数
数据流向:
装饰器作用域继承父传子适用场景@State组件内❌❌简单状态@Link组件内❌✅双向绑定@Prop组件内❌✅单向纯展示@ObjectLink组件内✅✅复杂对象@StorageLink持久化❌❌全局持久AppStorage应用级❌❌全局状态
typescript
// 统一网络服务
class HttpService {
private baseUrl = 'https://api.example.com';
async request<T>(config: RequestConfig): Promise<T> {
const http = http.createHttp();
try {
const response = await http.request(this.baseUrl + config.url, {
method: config.method || 'GET',
header: config.headers,
extraData: config.body,
connectTimeout: 30000,
readTimeout: 30000
});
http.destroy();
return JSON.parse(response.result as string) as T;
} catch (e) {
http.destroy();
throw e;
}
}
get<T>(url: string): Promise<T> {
return this.request<T>({ url, method: 'GET' });
}
post<T>(url: string, body: object): Promise<T> {
return this.request<T>({ url, method: 'POST', body });
}
}
// 使用
const httpService = new HttpService();
const users = await httpService.get<User[]>('/users');
方案适用场景容量性能AppStorage键值对小高relationalStore结构化数据中中userinfoStore用户数据中中requestDataHelper简单存储小高typescript
// AppStorage 使用
AppStorage.setOrCreate('username', 'John');
const username = AppStorage.get<string>('username');
// 持久化存储
import { userinfoStore } from '@kit.ArkData';
let context = getContext(this);
const store = await userinfoStore.getUserinfoStorageInstance(context);
await store.insert('user', { name: 'John', age: 30 });
const result = await store.query('user', []);
typescript
import router from '@ohos.router';
// 路由配置(main_pages.json)
{
"src": [
{
"name": "Home",
"pageSourceFile": "./ets/pages/Home/Home.ets",
"window": { "designWidth": 720 }
},
{
"name": "Detail",
"pageSourceFile": "./ets/pages/Detail/Detail.ets"
}
]
}
// 路由跳转
router.pushUrl({ url: 'pages/Detail/Detail', params: { id: 123 } });
// 获取参数
const params = router.getParams() as { id: number };
typescript
// 方式一:直接导入
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
// 方式二:服务发现
import serviceDiscovery from '@kit.ArkUI';
// 方式三:@ohos 兼容方式(已废弃,不推荐)
import UIAbility from '@ohos.app.ability.UIAbility';
场景方案说明长列表LazyForEach懒加载,仅渲染可见项图片Image + async load支持网络图片数据持久化relationalStoreSQLite 数据库并行任务taskpool多线程并行预加载prefetch提前加载数据减少刷新@ObjectLink细粒度更新
typescript
import { taskpool } from '@kit.ArkTS';
// 定义并发函数
@Concurrent
function heavyTask(numbers: number[]): number {
return numbers.reduce((sum, n) => sum + n, 0);
}
// 执行任务
let task = new taskpool.Task(heavyTask, [[1, 2, 3, 4, 5]]);
let result = await taskpool.execute(task);
// 取消任务
taskpool.cancelTask(task);
typescript
// 单元测试(import test from '@kit.ArkTS')
import test from '@kit.ArkTS';
@Entry
@Component
struct Calc {
@State result: number = 0;
add(a: number, b: number): number {
return a + b;
}
}
// UI 测试:使用 DevEco Studio 内置测试框架
// 性能测试:使用 hdc hilog 抓取性能日志
工具用途DevEco Studio断点调试、日志查看hitrace分布式追踪hdc shell命令行调试AppGallery Connect远程调试、性能监控typescript
// 日志打印
import hilog from '@ohos.hilog';
hilog.info(0x0000, 'UserModule', 'User login: %{public}s', username);
// 条件断点
// 在 DevEco Studio 中设置条件表达式
组件用途关键属性Text文本显示.fontSize(), .fontColor(), .fontWeight()Image图片.src(), .width(), .height(), .borderRadius()Button按钮.type(), .onClick(), .backgroundColor()TextInput输入框.placeholder(), .text(), .onChange()List列表ForEach, ListItem, .onScrollIndex()Grid网格ForEach, ListItem, .columnsTemplate()Column垂直布局.spacing(), .alignItems()Row水平布局.spacing(), .justifyContent()Stack层叠布局.alignContent()Flex弹性布局.direction(), .wrap()Navigator路由导航.target(), .type()Dialog对话框.title(), .content()ActionSheet操作菜单.actions()LoadingProgress加载指示器.width(), .height()Badge徽章.count(), .maxCount()Tabs标签页.barPosition(), .controller()
类型语法示例基础类型string, number, boolean``let name: string = 'John'数组Type[]``let nums: number[] = [1, 2, 3]元组[Type, Type]``let t: [string, number] = ['age', 30]枚举enum Name { A, B }``enum Color { Red, Blue }接口interface Name { }``interface User { id: number; name: string; }可空Type | null``let x: number | null = null联合A | B | C``let v: string | number | boolean字面量'a' | 'b' | 'c'``type Direction = 'up' | 'down'函数(params) => returnType``let fn: (n: number) => number类class Name { }``class User { name: string; }泛型Type<T>``let arr: Array<number>
权限用途级别ohos.permission.INTERNET网络访问normalohos.permission.GET_NETWORK_INFO获取网络信息restrictedohos.permission.CAMERA相机restrictedohos.permission.MICROPHONE麦克风restrictedohos.permission.RECORD_AUDIO录音restrictedohos.permission.READ_CONTACTS读联系人restrictedohos.permission.WRITE_CONTACTS写联系人restrictedohos.permission.LOCATION位置restrictedohos.permission.STORAGE存储restricted
功能模块方法HTTP请求@kit.NetworkKit``http.createHttp()文件操作@kit.CoreFileKit``fileio偏好设置@kit.AbilityKit``AppStorage弹窗@kit.ArkUI``promptAction路由@kit.ArkUI``router图片@kit.MediaKit``image视频@kit.MediaKit``video音频@kit.MediaKit``audio动画@kit.ArkUI``animateTo手势@kit.ArkUI``gesture线程池@kit.ArkTS``taskpool
typescript
// 垂直布局 Column
Column({ space: 10 }) {
Text('Header')
Row() { /* 内容 */ }
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
// 水平布局 Row
Row({ space: 12 }) {
Image('icon.png').width(24).height(24)
Text('Label')
Blank()
Text('Value')
}
.width('100%')
.padding(16)
// 弹性布局 Flex
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
ForEach(items, (item) => {
ItemComponent({ item: item })
.width('30%')
.margin(5)
})
}
// 层叠布局 Stack
Stack() {
Background()
Content()
FloatingButton()
}
.alignContent(Alignment.BottomEnd)
阶段说明回调创建组件创建aboutToAppear()渲染UI 构建build()销毁组件销毁aboutToDisappear()页面显示页面展示onPageShow()页面隐藏页面隐藏onPageHide()权限变更权限回调onAbilityConnectDone()
版本支持特性API 9基础 ArkTS + Stage 模型API 10增强类型系统API 11性能优化API 12@kit 导入方式API 22HTTP 拦截器
typescript
@Entry
@Component
struct MyPage {
@State message: string = 'Hello';
build() {
Column() {
Text(this.message)
}
}
}
typescript
// 方式一:Kit 方式(推荐)
import { UIAbility, Ability, Context } from '@kit.AbilityKit';
// 方式二:直接模块
import UIAbility from '@ohos.app.ability.UIAbility';
typescript
async function loadModule() {
let module = await import('./Calc');
module.add(3, 5);
}
文件内容references/arkts-language.mdArkTS 完整语法(类型/函数/类/接口/泛型/运算符/语句/模块/注解)references/arkui-quickref.mdArkUI 组件、装饰器、布局、路由、生命周期、动画、手势references/stage-config.mdStage 模型配置 + 窗口管理(UIAbility/子窗口/沉浸式/悬浮窗)references/app-package.mdHAP/HAR/HSP 包结构、Stage 模型配置references/resource-management.md资源目录、$r/$rawfile/$sys 语法、限定词、overlay、AppStoragereferences/network-http.mdHTTP 请求、WebSocket、文件上传下载、拦截器、证书配置references/permission-testing.md权限声明与动态请求、应用测试(单元/UI/性能)、签名发布流程、hvigor 构建references/media-ai-distributed.md媒体处理(image/video/audio)、Canvas、AI 能力、分布式数据、流转references/glossary.md
错误做法正确做法❌ let x = null✅ let x: number | null = null(所有类型默认非空)❌ obj instanceof Class 用于接口✅ instanceof 仅限 Class,不支持接口类型❌ 对象字面量随意扩属性✅ 禁止运行期改变对象布局❌ 动态增加对象属性✅ 静态类型禁止❌ 一元加法用于非数字✅ +str 会报错,一元加法仅能作用于数字
错误做法正确做法❌ 在 aboutToDisappear() 修改状态✅ 该方法禁止修改 @State,会触发 UI 异常❌ LazyForEach 不提供唯一键函数✅ 必须提供 (item) => item.id 类型的唯一键❌ HTTP 请求忘记 destroy()✅ 每次请求后调用 httpRequest.destroy() 防内存泄漏❌ router.pushUrl() 传复杂对象✅ params 仅支持基本类型,复杂数据用 AppStorage❌ 组件内直接修改 @Prop✅ @Prop 是单向传递,只能父组件修改
错误做法正确做法❌ module.json5 的 srcEntry 路径错误✅ 路径相对于项目根目录,如 ./ets/entryability/EntryAbility.ts❌ 混淆 HAP/ HAR/ HSP 用途✅ HAP 可安装,HAR 编译时打包,HSP 运行时共享❌ 免安装应用配置错误✅ installationFree: true 时 deliveryWithInstall 必须为 false❌ 权限只声明不动态请求✅ 敏感权限需同时声明和动态请求❌ 多设备场景硬编码 deviceId✅ 空字符串 '' 表示本设备,显式 deviceId 用于跨设备
@kit.AbilityKit 是 API v22+ 推荐方式.ets/ .d.ets 文件有效,release 混淆会被移除boolean/number/string 及其数组wrap: FlexWrap.Wrap 才能换行ForEach 在 Grid 内必须配合 ListItem() 使用当使用本技能回答用户问题时,遵循以下格式:
ArkTS 所有类型默认非空,
let x: number = null会编译错误。正确做法是声明为let x: number | null = null。访问可空变量时用??合并操作符:this.nick ?? ''。如果确认变量有值,可用!非空断言,但需确保运行时不为空。