查看: 511|回复: 3

RNOH 鸿蒙适配环境搭建与 Pressable 点击失效排查

[复制链接]
发表于 6 小时前 | 显示全部楼层 |阅读模式
背景:为什么用 RNOH 适配鸿蒙

作为一个写了三年 React Native 的开发者,笔者一直觉得鸿蒙离自己很远。直到领导在周会上要求 App 适配鸿蒙,才开始查 RNOH。RNOH 是 React Native for OpenHarmony 的缩写,可以理解为让 RN 跑在鸿蒙上的适配层。本文记录从零跑通第一个页面的过程,重点整理环境搭建、项目初始化、组件使用和排障经验。

环境搭建:DevEco Studio、环境变量与 Node 版本

第一步是安装 DevEco Studio。它是鸿蒙官方 IDE,下载速度较慢,笔者花了约两个小时才装好。Mac 上如果之前装过老版本,新版本可能报“应用已损坏”,需要在终端执行:
  1. xattr -cr /Applications/DevEco-Studio.app
复制代码

第二步是配置环境变量 RNOH_C_API_ARCH=1。官方文档有说明,但笔者一开始没注意,构建时出现 undefined is not an object、Cannot read property of null 等错误,排查后设置该变量、清缓存重新构建才恢复。
  1. # Windows 环境变量设置
  2. # 在系统变量里新建 RNOH_C_API_ARCH,值为 1
  3. # 不设置的话后面会遇到各种奇怪的问题,别问我怎么知道的
  4. # Mac 环境
  5. # 编辑 ~/.zshrc,添加:
  6. export RNOH_C_API_ARCH=1
  7. # 然后 source ~/.zshrc 生效
复制代码

第三步是安装 Node。RNOH 要求 Node 22.11.0 以上,笔者本地还是 20.x,用 nvm 升级:
  1. nvm install 22
  2. nvm use 22
复制代码

如果漏掉 nvm use 22,终端里仍是老版本,后续 npm install 可能报 engine 不兼容。

创建项目与 Metro 配置

用 RN 官方 CLI 创建项目:
  1. npx @react-native-community/cli init MyHarmonyApp
复制代码

然后安装鸿蒙适配依赖:
  1. npm install @react-native-oh/react-native-harmony
  2. npm install @react-native-oh/react-native-harmony-cli
复制代码

项目目录中,harmony 是鸿蒙工程核心,关键路径包括 harmony/entry/src/main/ets(ArkTS 代码)、cpp(C++ 桥接代码)、resources(资源文件),以及 build-profile.json5、oh-package.json5。src 目录放 RN 业务代码,App.tsx 是 RN 入口,metro.config.js 是 Metro 打包配置。

metro.config.js 必须加入 RNOH 的 Harmony Metro 配置,否则 Metro 能启动,但打包出的 bundle 在鸿蒙上会白屏:
  1. const {mergeConfig, getDefaultConfig} = require('@react-native/metro-config');
  2. const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');
  3. const config = {
  4.   transformer: {
  5.     getTransformOptions: async () => ({
  6.       transform: {
  7.         experimentalImportSupport: false,
  8.         inlineRequires: true,
  9.       },
  10.     }),
  11.   },
  12. };
  13. module.exports = mergeConfig(
  14.   getDefaultConfig(__dirname),
  15.   createHarmonyMetroConfig({
  16.     reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
  17.   }),
  18.   config
  19. );
复制代码

首次在 DevEco Studio 点运行,hvigor 构建会非常慢,笔者等了近五分钟,进度条几乎不动;第二次之后增量编译约十几秒。首次构建建议预留耐心。

第一个页面:计数器 Demo 验证基础 API

页面需求是计数器,点按钮加减、换背景色、弹窗。用到的 RN API 包括 useState 管理状态、Pressable 处理点击、Alert 弹窗、View/Text 渲染 UI、StyleSheet 写样式,没有第三方库。原文代码较长,核心是:最外层 View 用 justifyContent: 'center' 垂直居中;卡片内放标题、圆形计数器、按钮行、额外操作按钮和提示文字;计数按钮通过 setCount 更新,颜色按钮从预设色数组随机取值,弹窗按钮调用 Alert.alert。

这些基础 API 在鸿蒙上最终都跑通了,但过程中遇到不少兼容和工程配置问题。

六个典型踩坑与排障

坑 1:Pressable 的 onPress 不生效

最初用 TouchableOpacity,鸿蒙上点击没反应。社区反馈鸿蒙上 TouchableOpacity 有时有问题,建议用 Pressable。替换后点击恢复正常。
  1. // 错误写法:在鸿蒙上可能不生效
  2. <TouchableOpacity onPress={handlePress}>
  3.   <Text>点我</Text>
  4. </TouchableOpacity>
  5. // 正确写法:用 Pressable 更稳
  6. <Pressable onPress={handlePress}>
  7.   <Text>点我</Text>
  8. </Pressable>
复制代码

坑 2:Alert 弹窗样式不对

Alert.alert() 在鸿蒙上能用,但样式与 iOS、Android 差别较大,按钮文字颜色很淡,几乎看不清。原因是鸿蒙系统默认主题导致,目前 RN 的 Alert 在鸿蒙上适配还不完善。如果对样式有要求,需要自己写 Modal 组件替代。

坑 3:热更新偶尔失灵

开发中热更新有时失效:改了代码,Metro 提示编译成功,但设备页面不刷新。排查后确认是 DevEco Studio 缓存问题,需要手动清缓存再重新构建。
  1. hvigorw clean
复制代码

坑 4:SafeAreaView 不好使

在 iOS 上常用 SafeAreaView 处理刘海屏和底部安全区域,但在鸿蒙上行为奇怪,内容可能被顶到状态栏下面。鸿蒙上需要自己处理避让区域,或使用 RNOH 提供的 shim 方案;具体方案要看 RNOH 版本,建议查官方文档。

坑 5:构建 HAP 时签名问题

构建 HAP 时一直报签名错误,例如“签名文件不存在”或“签名验证失败”。鸿蒙应用必须签名才能安装到设备上,不像 Android 开发可以直接装 debug 版本。解决方式是在 DevEco Studio 的 Project Structure 中勾选“Automatically generate signature”,登录华为账号自动生成签名。

坑 6:bundle 文件放错位置

打包完 JS bundle 后,需要放到鸿蒙工程指定位置。笔者一开始放到 harmony/entry/src/main/resources/rawfile/,应用仍白屏。后来发现 bundle 文件名必须与鸿蒙代码里配置的一致,默认是 bundle.harmony.js;如果改名,鸿蒙侧代码也要同步修改。
  1. // harmony/entry/src/main/ets/pages/Index.ets
  2. // 这里的 bundle 文件名要跟你打包出来的文件名一致
  3. new ResourceJSBundleProvider(
  4.   this.rnohCoreContext.uiAbilityContext.resourceManager,
  5.   'bundle.harmony.js' // 这个名字要对上
  6. )
复制代码

验证结果与问题归类

最终计数器页面跑通,验证了 useState 正常工作、Pressable 点击事件正常触发、Alert 弹窗能弹出但样式较丑、StyleSheet 样式渲染没问题。踩坑主要集中在四类:组件兼容性(如 TouchableOpacity 点击可能失效,优先 Pressable)、系统 API 差异(Alert 样式与预期不同)、热更新不稳定(需手动清缓存)、安全区域处理(SafeAreaView 可能需要特殊处理)。

给 RN 开发者的适配建议

第一,不要一步到位。先写最简单的页面跑通,确认环境没问题,再逐步加功能。第二,多看 RNOH 官方文档和 GitHub Issues,很多问题社区已经有人踩过。第三,保持耐心。鸿蒙 RN 开发还在快速发展,部分能力不如 iOS、Android 成熟,但 RNOH 更新勤快,基本每月都有新版本。笔者开始用的是 0.72 版本,现已到 0.84,不少早期坑已被修复。

架构上也要取舍:如果只做鸿蒙,直接用 ArkTS 写更顺畅;但 App 要同时跑 iOS、Android、鸿蒙三个平台,维护三套代码成本太高。用 RN 可以复用业务逻辑,只有平台特定功能才写原生代码,长远看更划算。

后续计划

这个计数器 Demo 只是开胃菜。后续计划继续探索 TurboModule(RN 调用鸿蒙原生模块)、TTS 语音播报(Core Speech Kit)、OCR 文字识别(视觉能力)、小艺智能体(通过 Agent Framework Kit 拉起小艺),并分享实现过程和踩坑记录。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: RNOH 鸿蒙适配环境搭建与 Pressable 点击失效排查

感谢分享,这篇很实用,尤其是环境搭建部分。RNOH_C_API_ARCH=1 和 Node 22.11.0 以上这两个点确实很容易漏,漏了之后报 undefined 或者 engine 不兼容,排查起来很费时间。Metro 配置合并 Harmony 那段也很关键,否则 Metro 能跑但鸿蒙端白屏。Pressable 替代 TouchableOpacity 的经验也很实际,点击不生效时很容易怀疑业务代码。Alert 样式和热更新失效的坑也很有参考价值,首次 hvigor 构建慢到五六分钟这点也很真实。看到坑 4 SafeAreaView 好像没写完,鸿蒙上是不是得自己处理状态栏和底部安全区?如果方便的话,期待把六个坑补全,特别是 SafeAreaView 和后续排障细节。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: RNOH 鸿蒙适配环境搭建与 Pressable 点击失效排查

感谢分享,这篇对刚开始折腾 RNOH 的人挺有帮助。RNOH_C_API_ARCH=1 和 Node 22 这两个点确实关键,漏了之后报错很分散,不好定位。metro.config.js 不加 Harmony 配置会白屏这个提醒也很实用,因为 Metro 能启动很容易让人误判。Pressable 替代 TouchableOpacity、Alert 样式偏淡、热更新需要 hvigorw clean,这些都是真会耗时间的坑。首次 hvigor 构建慢也有同感,得预留耐心。坑 4 SafeAreaView 正看到关键处,期待后续把鸿蒙上安全区域的处理方式补完,这块对做页面适配很关键。收藏了,等更新。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: RNOH 鸿蒙适配环境搭建与 Pressable 点击失效排查

感谢楼主把 RNOH 从环境到排障写得这么细,对刚被安排适配鸿蒙的人太有用了。RNOH_C_API_ARCH 这个点真是坑,没设的话构建报 undefined 和 Cannot read property of null 很容易让人怀疑人生,Node 22 和 nvm use 也经常忘。Metro 配置那段很关键,不然 Metro 能启动但鸿蒙白屏,排查起来很费劲。Pressable 替换 TouchableOpacity 的经验很实在,Alert 样式和热更新清缓存也记下了。想问下后面 SafeAreaView 在鸿蒙上你最后是怎么处理的?首帖最后好像没写完,期待后续把这块也补上。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-16 21:13 , Processed in 0.026040 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部