ArkTS / ArkUI 基础知识参考字典

要点

鸿蒙入门到日常开发的名词条目分七组:状态装饰器、UI 组件、路由、生命周期、并发、网络与权限、报错速查。每条给签名、一句话定位、最小示例和坑;字典是查的,文末速查表做全量索引。语言层的”为什么”不在此展开,见系列第三篇。

状态管理装饰器(V1 / V2)

V1(@Component 系)与 V2(@ComponentV2 系)两套观测机制并存、不可混用;V1 观测第一层,V2 到属性级,工程内保持一致。

@State(V1)

@Component
struct Counter {
  @State count: number = 0    // 必须本地初始化
  build() {
    Button(`${this.count}`).onClick(() => { this.count += 1 })
  }
}

组件内部状态的默认选择,变化即刷新本组件。

⚠️ 坑:只观测第一层。this.list.push(x) 能刷新,this.list[0].done = true 不能。

@Prop / @Link(V1)

@Component
struct Child {
  @Prop title: string = ''       // 单向拷贝:父变我变,我变只影响自己
  @Link liked: boolean           // 双向:修改同步回父
  build() {
    Column({ space: 8 }) {
      Text(this.title)
      Toggle({ isOn: this.liked })
        .onChange((v: boolean) => { this.liked = v })
    }
  }
}
// 父组件调用:Child({ title: this.msg, liked: $isLiked })

@Prop 收快照、@Link 收引用,分别对应”只读展示”与”子组件可回写”。

⚠️ 坑:@Link 传值忘写 $ 前缀直接编译报错;@Prop 是深拷贝,传大对象有性能代价。

@Provide / @Consume(V1)

// 顶层:@Provide theme: string = 'dark'
// 任意深层后代:@Consume theme: string   按变量名匹配,免去逐层透传

跨层级共享,命名即通道。

⚠️ 坑:同名即配对,两个顶层 @Provide 同名变量时后代拿到谁不可预期。

@Observed + @ObjectLink(V1)

@Observed
class Task {
  done: boolean = false
}
@Component
struct TaskRow {
  @ObjectLink task: Task    // 不能本地初始化,必须由父传入
  build() {
    Text(this.task.done ? '完成' : '进行中')
      .onClick(() => { this.task.done = !this.task.done })  // 类内属性变化可观测
  }
}

V1 时代补嵌套观测的组合拳:可观察类 + 接收子组件。

⚠️ 坑:只观测该实例自身的属性,属性的属性(再嵌套一层)仍看不见。

@ComponentV2 + @Local / @Param / @Event(V2)

@ComponentV2
struct PriceCard {
  @Local selected: boolean = false      // 取代 @State
  @Param price: number = 0              // 外部只读传入
  @Event onBuy: () => void = () => {}   // 子到父的事件回调
  build() {
    Text(`¥${this.price}`)
      .onClick(() => { this.selected = true; this.onBuy() })
  }
}

V2 组件三件套:本地状态、只读入参、显式回调,双向绑定拆成下行数据 + 上行事件。

⚠️ 坑:在 @ComponentV2 里写 @State、在 @Component 里写 @Local,都直接报”装饰器不适用”。

@ObservedV2 + @Trace(V2)

@ObservedV2
class Cart {
  @Trace items: string[] = []     // 属性级观测:第 N 层变化都刷新
  @Trace total: number = 0
  note: string = ''               // 未标 @Trace:怎么改都不触发 UI
}

属性级深度观测,嵌套刷新问题的终点。

⚠️ 坑:类里漏标 @Trace 的属性是观测盲区,编译器不会替你检查”忘了标”。

@Monitor(V2)

@ComponentV2
struct Page {
  @Local page: number = 1
  @Monitor('page')                       // 监听状态变量名
  onPageChange() {                       // 回调可带 IMonitor 参数取变化前后值
    console.info('翻页了')
  }
}

声明式的”watch”,替代在 onClick 里手写副作用。

UI 组件

组内共性:属性全部链式调用,没有 CSS;布局组件自身就是 flex 语义。

Text / Button / TextInput

Text('标题').fontSize(20).fontWeight(FontWeight.Bold)
Button('提交', { type: ButtonType.Capsule }).width('50%')
TextInput({ placeholder: '搜索' })
  .onChange((v: string) => { /* v 即最新输入 */ })

三大基础件;Button 内容也可换成子组件。

⚠️ 坑:TextInput 的值由状态驱动时,onChange 里要同步写回状态,否则输入框”自己显示”与状态脱节。

Column / Row / Stack

Column({ space: 12 }) { /* 垂直排 */ }
Row({ space: 8 }) { /* 水平排 */ }
Stack({ alignContent: Alignment.BottomEnd }) { /* 叠放,后者盖前者 */ }

布局三板斧,space 是子项间距,对齐用 justifyContent / alignItems 两族属性。

⚠️ 坑:Row 里想让某项占满剩余宽度用 layoutWeight(1),不存在 flex-grow 这个属性名。

List + ForEach

List({ space: 8 }) {
  ForEach(this.todos, (item: Todo) => {
    ListItem() { Text(item.title) }
  }, (item: Todo) => item.id.toString())   // key 生成器
}.layoutWeight(1)

滚动列表的标准写法,ListItem 是直接子节点。

⚠️ 坑:key 用下标,删除中间项即错位;key 必须稳定且唯一。

Grid

Grid() {
  GridItem() { Text('1') }
  GridItem() { Text('2') }
}
.columnsTemplate('1fr 1fr')   // 两列等宽;fr 单位表达比例

网格容器,配 GridItem 使用;响应式栅格另有 GridRow/GridCol 一套。

⚠️ 坑:不设 columnsTemplate 时接近单列,忘了配是最常见的”没成网格”。

路由

官方推荐 Navigation(组件式导航);@ohos.router(页面级路由)停止演进、存量仍在用。两条路线并存,新项目选 Navigation。

Navigation + NavDestination

@Component
struct Home {
  pathStack: NavPathStack = new NavPathStack()
  build() {
    Navigation(this.pathStack) {
      Button('详情').onClick(() => {
        this.pathStack.pushPathByName('detail', 42)   // 压栈并传参
      })
    }
    .navDestination(this.pageMap)
  }
  @Builder pageMap(name: string) {
    if (name === 'detail') { Detail() }
  }
}
@Component
struct Detail {
  build() {
    NavDestination() { Text('详情页') }
  }
}

页面栈由 NavPathStack 持有,push/pop/replace 都在它上面调,转场与返回手势由框架接管。

⚠️ 坑:目的页忘了包 NavDestination,页面能 push 但标题栏与返回行为都不对。

@ohos.router(旧路线)

import { router } from '@kit.ArkUI'

router.pushUrl({ url: 'pages/Detail' })   // 目标页必须先注册

命令式跳转,直观但扩展性差,官方已停止加新能力。

⚠️ 坑:目标页面必须注册进 resources/base/profile/main_pages.json,漏注册直接报错。

生命周期

分三层:UIAbility(应用级)、页面(@Entry)、组件(@Component),回调全靠覆写方法。

组件:aboutToAppear / aboutToDisappear

@Component
struct Feed {
  aboutToAppear() { /* build 之前:初始化状态、发首个请求 */ }
  aboutToDisappear() { /* 销毁前:取消订阅、释放资源 */ }
  build() { /* ... */ }
}

组件创建与销毁的两端,等价于 React 的 mount/unmount effect。

⚠️ 坑:把请求写在 build() 里——build 会被框架多次调用,副作用成倍执行。

页面:onPageShow / onPageHide / onBackPress

@Entry
@Component
struct Index {
  onPageShow() { /* 每次页面回到前台触发,含路由返回 */ }
  onBackPress(): boolean { return false }   // 返回 true 表示已拦截返回键
  build() { /* ... */ }
}

页面级可见性回调,只对 @Entry 页面有效。

⚠️ 坑:”从详情页返回列表”要刷新时,aboutToAppear 不触发(组件没销毁),要写 onPageShow。

UIAbility:onCreate → onWindowStageCreate → onForeground/onBackground → onDestroy

// EntryAbility.ets 里覆写;onWindowStageCreate 中 loadContent('pages/Index')
onForeground(): void { /* 应用回到前台 */ }
onBackground(): void { /* 应用退到后台:停轮询、保存草稿 */ }

应用进程级回调,频率低,适合放全局资源管理。

并发

ArkTS 事件循环与 UI 隔离,多线程只有两条路——TaskPool(任务)与 Worker(线程),数据都经序列化拷贝传递。

taskpool + @Concurrent

import { taskpool } from '@kit.ArkTS'

@Concurrent
function heavyParse(raw: string): number {     // 独立线程执行:不能碰 UI 与状态
  return raw.split(',').length
}

taskpool.execute(heavyParse, input)            // 返回 Promise
  .then((n: number) => console.info(`${n} 项`))

一次性计算/IO 任务的首选,线程池自动管理复用,官方默认推荐。

⚠️ 坑:@Concurrent 函数里访问组件状态或全局单例——跨线程数据必须靠参数传值与返回值。

Worker

import { worker } from '@kit.ArkTS'

const w = new worker.ThreadWorker('entry/ets/workers/Calc.ets')
w.postMessage(data)      // 双向消息通信
w.onmessage = (e) => { /* e.data 为回传结果 */ }
w.terminate()            // 生命周期手动管理

长驻线程:持续通信、后台循环这类”活着比完成任务重要”的场景。

⚠️ 坑:路径写错启动即崩;忘记 terminate 是泄漏。口诀:任务用 TaskPool,线程用 Worker。

网络与权限

权限先声明后使用,落点在 module.json5。环境与签名问题回《鸿蒙开发环境搭建》。

module.json5 权限声明

{
  "module": {
    "requestPermissions": [
      // system_grant:安装即授予,只需 name
      { "name": "ohos.permission.INTERNET" },
      // user_grant:需 reason + usedScene,运行时弹窗申请
      {
        "name": "ohos.permission.CAMERA",
        "reason": "$string:camera_reason",
        "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
      }
    ]
  }
}

权限分 system_grant(声明即得)与 user_grant(运行时申请)两类。

⚠️ 坑:user_grant 权限只声明不运行时申请,调 API 直接失败;reason 引用的字符串资源不存在会在打包时报错。

@ohos.net.http 请求

import { http } from '@kit.NetworkKit'

function getJson(url: string): Promise<string> {
  const client = http.createHttp()
  return client.request(url, { method: http.RequestMethod.GET })
    .then((resp: http.HttpResponse) => {
      if (resp.responseCode === 200) {
        return resp.result as string      // result 是 string | Object | ArrayBuffer
      }
      throw new Error(`HTTP ${resp.responseCode}`)
    })
    .finally(() => client.destroy())     // 用完销毁
}

系统 HTTP 客户端,Promise 风格,复杂项目可再封装。

⚠️ 坑:权限没声明时请求直接抛错,不是慢;明文 HTTP 可能被安全策略拦截,调试优先 HTTPS,放行配置以官方《网络安全配置》文档为准。

常见报错速查

现象 / 报错 常见原因 修法
改了数据界面不动 @State 只观测第一层 整对象替换;V2 @ObservedV2/@Trace;或 @Observed+@ObjectLink
ForEach 增删后列表错乱 key 缺失、用下标或 key 重复 keyGenerator 返回稳定业务 id
“装饰器不适用”类报错 V1/V2 混用(@Component 里写 @Local 等) 组件整体迁 V2,或退回 V1
arkts-no-untyped-obj-literals 对象字面量没有类型归属 给变量或字面量标注类型(class/interface)
arkts-no-structural-typing 类型仅”长得像”就互相赋值 显式 implements / extends 建立继承关系
http 请求抛错 / 一直失败 没声明 INTERNET 权限 requestPermissions 加 ohos.permission.INTERNET 后重装
跳转页面报”页面未注册” 新页面没写进 main_pages.json 在 main_pages.json 的 src 数组补路径
真机安装失败 未签名 / 证书过期 / 设备未入 Profile 重新自动签名;查证书额度与 USB 调试
预览器白屏或”不支持预览” 页面用了预览器不支持的系统 API 换模拟器或真机验证
@Concurrent 函数里改 UI 状态无效 子线程无法访问 UI 与状态 结果经 Promise 返回主线程再更新

速查表

条目 一句话用途 有什么坑
@State (V1) 组件内部状态 只观测第一层
@Prop (V1) 父到子单向拷贝 深拷贝开销
@Link (V1) 父子双向同步 父侧传值要加 $
@Provide/@Consume (V1) 跨层级共享 同名匹配,重名覆盖
@Observed+@ObjectLink (V1) 嵌套对象观测 @ObjectLink 不能本地初始化
@Local (V2) 取代 @State 不能与 V1 装饰器混用
@Param+@Event (V2) 只读入参 + 显式回调 @Param 内部赋值即错
@ObservedV2+@Trace (V2) 属性级深度观测 漏标 @Trace 是盲区
@Monitor (V2) 声明式监听变化 参数是变量名字符串
Column/Row/Stack 三大布局容器 占位用 layoutWeight 不是 flex
List+ForEach 滚动列表 key 用下标必错乱
Grid 网格布局 不配 columnsTemplate 不成网格
Navigation/NavPathStack 官方推荐导航 目的页要包 NavDestination
@ohos.router 旧页面路由 停止演进,新项目别选
aboutToAppear 组件初始化 副作用别放 build
onPageShow 页面回前台 返回刷新场景用它
UIAbility 生命周期 应用级回调 onBackground 里保存状态
taskpool+@Concurrent 一次性并发任务 子线程摸不到 UI
Worker 长驻线程 手动 terminate
http 模块 系统网络请求 权限未声明直接抛错
requestPermissions module.json5 权限声明 user_grant 还要运行时申请

下一步

字典覆盖入门到日常开发的查表需求,定制动画、NDK、跨设备流转等深水区不在其列,以官方文档为准。实感来自《第一个鸿蒙应用》,语言约束见《ArkTS 语法要点》;写过 Flutter 的读者可对照《Flutter 基础知识参考字典》。

版本核实(撰写时检索,2025-01):V1 状态装饰器为 API 9 起体系,V2(@ComponentV2/@Local/@Param/@Event/@ObservedV2/@Trace/@Monitor)自 API 12 起提供且为官方主推方向,两套不可混用;@ohos.router 不再获得新能力、官方推荐 Navigation;并发推荐 TaskPool;http 需声明 ohos.permission.INTERNET。当前 Release SDK 配套 HarmonyOS NEXT 5.0(API 12),API 可用性与参数细节以 developer.huawei.com 官方文档为准。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇