鸿蒙 6.1 API 23 开发坑系列篇 5arkui.observer UI 观察器坑——uiObserver namespace 真名不是 observer on type 是 string literal 不是 enum 根因本文是「鸿蒙 6.1 API 23 开发坑系列」第 5 篇ArkUI 桶第 5 篇。本篇讲ohos.arkui.observernamespaceAPI 11鸿蒙 6.1 API 23 基座——UI 观察器uiObservernamespace on(type, callback)/off(type, callback) 7 种 type ScrollEventInfo/NavDestinationInfo。鸿蒙坑根因① namespace 真名是uiObserver不是observerimport { observer } from编译错has no exported member必须import uiObserver fromdefault import不是 named import②on(type, callback)的 type 参数是string literalscrollEvent不是 enumScrollEventType③ScrollEventInfo/ObserverOptions/NavDestinationInfo/NavDestinationState都嵌套在 namespace uiObserver 里不是顶层 exportimport { ScrollEventInfo }编译错必须uiObserver.ScrollEventInfo命名空间访问④ScrollEventInfo没有type属性React scroll event 有type鸿蒙没有真属性是id/uniqueId/offset/triggerOffset/observableScrollableTotalRange⑤on支持 7 种 type string literalscrollEvent/navDestinationUpdate/routerPageUpdate/densityUpdate/willDraw/didLayout/tabContentUpdate/navDestinationSwitch。一、开篇鸿蒙 uiObserver 不是 React addEventListener是「namespace 顶层函数 on/off」你写 React 时UI 事件监听用addEventListenertype 是 enum/string回调传 Event 对象// React addEventListenertype 是 string/enum回调传 Event 对象 element.addEventListener(scroll, (event: Event) { // ❌ React type 是 string scroll console.log(event.type) // ❌ React Event 有 type 属性scroll })你写鸿蒙 ArkTS 时UI 观察器用uiObserver.on(type, callback)namespace 顶层函数type 是 string literal// ArkTS uiObserver.onnamespace 顶层函数type 是 string literal 不是 enum import uiObserver from ohos.arkui.observer // ✅ default import不是 { uiObserver } uiObserver.on(scrollEvent, (info: uiObserver.ScrollEventInfo) { // ✅ type 是 string literal scrollEvent // ✅ ScrollEventInfo 嵌套在 namespace uiObserver 里不是顶层 export // ✅ ScrollEventInfo 没有 type 属性React Event 有 type鸿蒙没有 console.log(uniqueId: ${info.uniqueId}, offset: ${info.offset}) // ✅ 真属性是 uniqueId/offset }) // 鸿蒙坑根因namespace 真名是 uiObserver 不是 observeron type 是 string literal 不是 enumReact addEventListener vs 鸿蒙 uiObserver.on 的区别React 把事件监听当 DOM 方法element.addEventListener(scroll, cb)type 是 string/enum回调传 Event 对象有type属性ArkTS 把 UI 观察器当 namespace 顶层函数uiObserver.on(scrollEvent, cb)type 是 string literal 不是 enum回调传ScrollEventInfo嵌套在 namespace 里没有type属性。根因不是 DOM 方法是 namespace 顶层函数——鸿蒙 uiObserver.on 的 type 是 string literalScrollEventInfo 嵌套在 namespace 里没有 type 属性。二、根因鸿蒙 arkui.observer 的五个绑定机制鸿蒙ohos.arkui.observernamespaceAPI 11核心导出uiObservernamespacedefault exporton(type, callback)/off(type, callback)顶层函数 ScrollEventInfo/ObserverOptions/NavDestinationInfo/NavDestinationState/ScrollEventType嵌套类型。绑定机制来自五重根因。机制 1namespace 真名是 uiObserver 不是 observer——default import 不是 named import鸿蒙坑根因namespace 真名是uiObserver且是default export不是 named export// ❌ 鸿蒙坑import { observer } from 编译错namespace 真名是 uiObserver 不是 observer import { observer } from ohos.arkui.observer // ❌ has no exported member observer // ❌ import { uiObserver } from ohos.arkui.observer // ❌ 也编译错default export 不是 named export // ✅ 正确用法default importuiObserver 是 default export 不是 named export import uiObserver from ohos.arkui.observer // ✅ default import // 鸿蒙坑根因namespace 真名是 uiObserver 不是 observer且是 default export 不是 named exportnamespace 真名坑根因ohos.arkui.observer的.d.ts声明是declare default namespace uiObserverdefault namespace export真名uiObserver不是observer所以import { observer }触发has no exported member observer编译错import { uiObserver }触发has no exported member uiObserverdefault export 不能 named import。正确用法是import uiObserver fromdefault import。鸿蒙坑namespace 真名uiObserver不是observer文件名observer但 namespace 名uiObserver且是 default export 必须 default import。机制 2on 的 type 参数是 string literal 不是 enum——“scrollEvent” 不是 ScrollEventType鸿蒙坑根因on(type, callback)的 type 参数是string literal不是 enum// ❌ 鸿蒙坑on 的 type 传 enum 编译错type 是 string literal 不是 enum import uiObserver from ohos.arkui.observer // ❌ 编译错Argument of type ScrollEventType is not assignable to parameter of type string uiObserver.on(ScrollEventType.SCROLL_START, callback) // ❌ type 不是 enum 是 string literal // ✅ 正确用法type 传 string literal scrollEvent不是 enum ScrollEventType uiObserver.on(scrollEvent, callback) // ✅ type 是 string literal scrollEvent // 鸿蒙坑根因on 的 type 是 string literalscrollEvent不是 enumScrollEventTypetype string literal 坑根因uiObserver.on(type: string, callback: AsyncCallbackScrollEventInfo): void的 type 参数类型是stringstring literal不是 enumScrollEventType。鸿蒙坑传 enumScrollEventType.SCROLL_START触发Argument of type ScrollEventType is not assignable to parameter of type string编译错——必须传 string literalscrollEvent。ScrollEventTypeenumSCROLL_START0/SCROLL_STOP1是ScrollEventInfo.type属性的值类型但ScrollEventInfo实际没有type属性见机制 4不是on的 type 参数。机制 3ScrollEventInfo/ObserverOptions/NavDestinationInfo 嵌套在 namespace 里——不是顶层 export鸿蒙坑根因ScrollEventInfo/ObserverOptions/NavDestinationInfo/NavDestinationState都嵌套在 namespace uiObserver 里不是顶层 export// ❌ 鸿蒙坑import { ScrollEventInfo } from 编译错嵌套在 namespace uiObserver 里不是顶层 export import { ScrollEventInfo, ObserverOptions, NavDestinationInfo } from ohos.arkui.observer // ❌ has no exported member // ✅ 正确用法用 uiObserver.ScrollEventInfo 命名空间访问嵌套在 namespace uiObserver 里 import uiObserver from ohos.arkui.observer uiObserver.on(scrollEvent, (info: uiObserver.ScrollEventInfo) { // ✅ uiObserver.ScrollEventInfo const options: uiObserver.ObserverOptions { id: scrollTarget } // ✅ uiObserver.ObserverOptions uiObserver.on(navDestinationUpdate, (navInfo: uiObserver.NavDestinationInfo) { // ✅ uiObserver.NavDestinationInfo } }) // 鸿蒙坑根因ScrollEventInfo/ObserverOptions/NavDestinationInfo 嵌套在 namespace uiObserver 里不是顶层 export嵌套 namespace 坑根因ohos.arkui.observer.d.ts的declare default namespace uiObserver { export interface ScrollEventInfo { ... } }——ScrollEventInfo/ObserverOptions/NavDestinationInfo/NavDestinationState/ScrollEventType都声明在namespace uiObserver { }块内嵌套 export不是顶层 export。鸿蒙坑import { ScrollEventInfo }触发has no exported member ScrollEventInfo编译错——必须用uiObserver.ScrollEventInfo命名空间访问。机制 4ScrollEventInfo 没有 type 属性——真属性是 id/uniqueId/offset/triggerOffset鸿蒙坑根因ScrollEventInfo没有type属性React Event 有type鸿蒙没有// ❌ 鸿蒙坑ScrollEventInfo 没有 type 属性React Event 有 type鸿蒙没有 import uiObserver from ohos.arkui.observer uiObserver.on(scrollEvent, (info: uiObserver.ScrollEventInfo) { // ❌ 编译错Property type does not exist on type ScrollEventInfo console.log(info.type) // ❌ ScrollEventInfo 没有 type 属性React Event 有 type鸿蒙没有 // ✅ 正确用法用真属性 id/uniqueId/offset/triggerOffset/observableScrollableTotalRange console.log(uniqueId: ${info.uniqueId}) // ✅ uniqueId 滚动组件唯一 id console.log(offset: ${info.offset}) // ✅ offset 滚动偏移量 console.log(triggerOffset: ${info.triggerOffset}) // ✅ triggerOffset 触发偏移量 console.log(observableScrollableTotalRange: ${info.observableScrollableTotalRange}) // ✅ 可观察滚动总范围 }) // 鸿蒙坑根因ScrollEventInfo 没有 type 属性真属性是 id/uniqueId/offset/triggerOffsetScrollEventInfo 无 type 坑根因uiObserver.ScrollEventInfo的真属性是id: ResourceStr组件 id、uniqueId: string唯一 id、offset: number滚动偏移量、triggerOffset: number触发偏移量、observableScrollableTotalRange: ObservableScrollableTotalRange可观察滚动总范围。鸿蒙坑ReactEvent有type属性scroll鸿蒙ScrollEventInfo没有type属性——传info.type触发Property type does not exist on type ScrollEventInfo编译错。ScrollEventTypeenumSCROLL_START0/SCROLL_STOP1不是ScrollEventInfo.type属性的值类型ScrollEventInfo无type属性是别处的 enum。机制 5on 支持 7 种 type string literal——scrollEvent/navDestinationUpdate 等鸿蒙坑根因on支持 7 种 type string literal每个对应不同 Info 类型// ✅ on 支持 7 种 type string literal每个对应不同 Info 类型 import uiObserver from ohos.arkui.observer // ✅ 7 种 type string literal uiObserver.on(scrollEvent, (info: uiObserver.ScrollEventInfo) { }) // ✅ 滚动事件 uiObserver.on(navDestinationUpdate, (info: uiObserver.NavDestinationInfo) { }) // ✅ NavDestination 路由更新 uiObserver.on(routerPageUpdate, (info: uiObserver.RouterPageInfo) { }) // ✅ Router 页面更新 uiObserver.on(densityUpdate, (info: uiObserver.DensityInfo) { }) // ✅ Density 更新 uiObserver.on(willDraw, () { }) // ✅ 将要绘制无 Info 参数 uiObserver.on(didLayout, () { }) // ✅ 布局完成无 Info 参数 uiObserver.on(tabContentUpdate, (info: uiObserver.TabContentInfo) { }) // ✅ TabContent 更新 // ✅ 还有 navDestinationSwitchAPI 11NavDestination 切换 // 鸿蒙坑根因on 支持 7 种 type string literal每个对应不同 Info 类型7 种 type string literal 坑根因uiObserver.on(type: string, callback)的 type 支持 7 种 string literalscrollEvent滚动事件回调传ScrollEventInfo、navDestinationUpdateNavDestination 路由更新回调传NavDestinationInfo、routerPageUpdateRouter 页面更新回调传RouterPageInfo、densityUpdateDensity 更新回调传DensityInfo、willDraw将要绘制无 Info 参数、didLayout布局完成无 Info 参数、tabContentUpdateTabContent 更新回调传TabContentInfo、navDestinationSwitchAPI 11NavDestination 切换。鸿蒙坑ReactaddEventListenertype 是 DOM 事件名scroll/click鸿蒙uiObserver.ontype 是 7 种 string literalscrollEvent不是scroll驼峰命名带Event后缀。三、真机配图鸿蒙 arkui.observer UI 观察器坑——uiObserver namespace on/off真机配图展示鸿蒙 arkui.observer UI 观察器坑初始态鸿蒙 6.1 arkui.observer UI 观察器坑标题滚动目标组件绿框 idscrollTarget5 行滚动内容场景1~5 卡片namespace 真名/on scrollEvent/onObserverOptions/off scrollEvent/on navDestinationUpdate要点说明namespace on scrollEvent 态点击「① 验证 namespace 真名」「② 验证 on scrollEvent」「③ 验证 on ObserverOptions」按钮显示「✅ uiObserver namespace 真名不是 observer」「✅ uiObserver.on(“scrollEvent”, callback) 监听滚动事件验证成功」「✅ 带 ObserverOptions 监听指定 id 验证成功」——namespace 真名 on type string literal ObserverOptions 验证滑后态下滑后显示场景4off scrollEvent 场景5on navDestinationUpdate 要点说明off navDestinationUpdate 怺态点击「⑦ 验证 off scrollEvent」「⑤ 验证 on navDestinationUpdate」按钮显示「✅ uiObserver.off(“scrollEvent”, callback) 取消监听验证成功」「✅ uiObserver.on(“navDestinationUpdate”, callback) 监听 NavDestination 路由验证成功」——off callback 同引用 navDestinationUpdate 验证四、真解法鸿蒙 arkui.observer 的四个场景场景 1uiObserver namespace default import on(‘scrollEvent’)——90% 场景首选uiObserver on 监听用import uiObserver fromuiObserver.on(scrollEvent, callback)// ✅ 场景 1uiObserver namespace default import on(scrollEvent)API 1190% 场景首选 import uiObserver from ohos.arkui.observer // ✅ default import不是 { uiObserver } Entry Component struct Index { aboutToAppear() { // ✅ on(scrollEvent, callback) 监听滚动事件——type 是 string literal 不是 enum uiObserver.on(scrollEvent, (info: uiObserver.ScrollEventInfo) { // ✅ uiObserver.ScrollEventInfo 命名空间访问 // ✅ ScrollEventInfo 没有 type 属性真属性是 uniqueId/offset/triggerOffset console.log(uniqueId: ${info.uniqueId}, offset: ${info.offset}) // ✅ 真属性 }) } build() { Column({ space: 8 }) { Text(demo) } } } // uiObserver namespace default import on(scrollEvent)90% 场景首选type 是 string literal鸿蒙 arkui.observer API 真名坑import uiObserver from ohos.arkui.observerdefault import 不是 named importnamespace 真名uiObserver不是observeruiObserver.on(type: string, callback: AsyncCallbackScrollEventInfo): voidnamespace 顶层函数type 是 string literal 不是 enumuiObserver.off(type: string, callback?: AsyncCallbackT): void取消监听callback 可选不传取消所有ScrollEventInfo/ObserverOptions/NavDestinationInfo嵌套在 namespace uiObserver 里用uiObserver.ScrollEventInfo命名空间访问SysCapSystemCapability.ArkUI.ArkUI.Fullcrossplatform跨平台atomicservice原子化服务。场景 2on(‘scrollEvent’, ObserverOptions, callback) 带 options 监听指定 idon 带 options 用uiObserver.on(scrollEvent, { id: xxx }, callback)监听指定组件 id// ✅ 场景 2on(scrollEvent, ObserverOptions, callback) 带 options 监听指定 idAPI 11 import uiObserver from ohos.arkui.observer uiObserver.on(scrollEvent, { id: scrollTarget }, (info: uiObserver.ScrollEventInfo) { // ✅ ObserverOptions { id: string } // ✅ 只监听 idscrollTarget 组件的滚动事件不传 options 监听所有组件 console.log(uniqueId: ${info.uniqueId}) // ✅ uniqueId 是滚动组件唯一 id }) // on ObserverOptions指定监听哪个组件 id 的滚动事件不传 options 监听所有组件鸿蒙 on ObserverOptions API 真名坑uiObserver.on(type: string, options: ObserverOptions, callback: AsyncCallbackScrollEventInfo): void重载带 options 指定监听组件 iduiObserver.ObserverOptions接口{ id: string }id 指定监听哪个组件string 类型鸿蒙坑不传 options 时监听所有组件的滚动事件传 options 时只监听指定 id 组件——ReactaddEventListener监听特定 DOM 元素鸿蒙uiObserver.on用ObserverOptions.id指定监听组件。场景 3off(‘scrollEvent’, callback) 取消监听——callback 传同一个引用off 取消监听用uiObserver.off(scrollEvent, callback)callback 必须传同一个引用// ✅ 场景 3off(scrollEvent, callback) 取消监听——callback 传同一个引用API 11 import uiObserver from ohos.arkui.observer // ✅ 先存 callback 引用off 时传同一个引用不是匿名函数 const scrollCallback: (info: uiObserver.ScrollEventInfo) void (info: uiObserver.ScrollEventInfo) { console.log(uniqueId: ${info.uniqueId}) } uiObserver.on(scrollEvent, scrollCallback) // ✅ on 时存 callback 引用 uiObserver.off(scrollEvent, scrollCallback) // ✅ off 时传同一个 callback 引用 // ✅ off callback 可选不传则取消所有 scrollEvent 监听 uiObserver.off(scrollEvent) // ✅ 不传 callback 取消所有监听 // off callback 传同一个引用不是匿名函数不传则取消所有监听鸿蒙 off API 真名坑uiObserver.off(type: string, callback?: AsyncCallbackT): void取消监听callback 可选鸿蒙坑off 的 callback 必须传同一个引用不是匿名函数匿名函数每次创建新引用无法匹配取消不传 callback 则取消该 type 的所有监听——ReactremoveEventListener也要求传同一个 callback 引用鸿蒙uiObserver.off同理。场景 4on(‘navDestinationUpdate’) 监听 NavDestination 路由更新on navDestinationUpdate 用uiObserver.on(navDestinationUpdate, callback)监听 NavDestination 路由// ✅ 场景 4on(navDestinationUpdate, callback) 监听 NavDestination 路由更新API 11 import uiObserver from ohos.arkui.observer uiObserver.on(navDestinationUpdate, (info: uiObserver.NavDestinationInfo) { // ✅ uiObserver.NavDestinationInfo // ✅ NavDestinationInfo 嵌套在 namespace uiObserver 里不是顶层 export // ✅ NavDestinationInfo 真属性navigator/context/from/to——具体看 SDK 声明 console.log(NavDestination 路由更新触发) }) // on navDestinationUpdate监听 NavDestination 路由更新NavDestinationInfo 嵌套在 namespace 里鸿蒙 on navDestinationUpdate API 真名坑uiObserver.on(navDestinationUpdate, callback: AsyncCallbackNavDestinationInfo): void监听 NavDestination 路由更新uiObserver.NavDestinationInfo嵌套在 namespace uiObserver 里用uiObserver.NavDestinationInfo命名空间访问不是顶层 export鸿蒙坑NavDestinationInfo的真属性不是 React 习惯的from/to具体属性看 SDK 声明直接访问info.from/info.to可能触发Property does not exist编译错——先查 SDK 真属性再用。五、一句话哲学写鸿蒙 ArkUI 记住uiObserver 不是 React addEventListener 是「namespace 顶层函数 on/off」——鸿蒙 6.1 API 23ohos.arkui.observernamespaceAPI 11鸿蒙 6.1 API 23 基座uiObservernamespace default export on/off顶层函数 7 种 type ScrollEventInfo/NavDestinationInfo嵌套类型SysCap SystemCapability.ArkUI.ArkUI.Fullcrossplatform atomicservice。根因不是 DOM 方法是 namespace 顶层函数——namespace 真名是uiObserver不是observer✅import uiObserver fromdefault import不是 named import❌import { observer } from编译错has no exported member observer❌import { uiObserver } from编译错default export 不能 named importon(type, callback)的 type 参数是string literal✅scrollEvent不是 enumScrollEventType❌ 传 enum 触发Argument of type ScrollEventType is not assignable to parameter of type stringScrollEventInfo/ObserverOptions/NavDestinationInfo/NavDestinationState/ScrollEventType都嵌套在 namespace uiObserver 里不是顶层 export✅uiObserver.ScrollEventInfo命名空间访问❌import { ScrollEventInfo }编译错has no exported memberScrollEventInfo没有type属性✅ 真属性id/uniqueId/offset/triggerOffset/observableScrollableTotalRange❌info.type触发Property type does not exist编译错ReactEvent有type鸿蒙ScrollEventInfo没有on支持 7 种 type string literalscrollEvent/navDestinationUpdate/routerPageUpdate/densityUpdate/willDraw/didLayout/tabContentUpdate/navDestinationSwitch每个对应不同 Info 类型Reactscroll鸿蒙scrollEvent驼峰命名带Event后缀off(type, callback)取消监听callback 必须传同一个引用不是匿名函数不传则取消该 type 所有监听。namespace 真名 uiObserver default import on type string literal ScrollEventInfo 嵌套 namespace 无 type 属性是鸿蒙 6.1 arkui.observer UI 观察器坑核心能力系列回链鸿蒙 7.0 新特性篇 1~17沉浸式毛玻璃/Component3D/智能体框架/方舟引擎/星盾安全/星河互联/空间音频/可变字体/游戏快启/分布式数据盾/LTPO 可变帧率/AI 文档识别/多形态服务窗口/AI 反诈/机密计算/空间计算/小艺全面进化鸿蒙 6.1 API 23 开发坑系列篇 1「ArkUI.modifier 装饰器坑」——attributeModifier AttributeModifier 状态化节点修改器鸿蒙 6.1 API 23 开发坑系列篇 2「arkui.componentSnapshot 组件截图坑」——get/getSync/createFromBuilder 返回 image.PixelMap 像素图鸿蒙 6.1 API 23 开发坑系列篇 3「arkui.node 节点坑」——NodeController abstract class makeNode override BuilderNode WrappedBuilder鸿蒙 6.1 API 23 开发坑系列篇 4「arkui.UIContext UI 上下文坑」——runScopedTask 不是 runScopedOnUiThread 11 个子管理器鸿蒙 6.1 API 23 开发坑系列篇 5「arkui.observer UI 观察器坑」——uiObserver namespace 真名不是 observer on type string literal本文