1. 为什么要把React Native和鸿蒙组件绑定在一起
1.1 需求从哪来:不是炫技,是业务逼的
最近在做一个跨端项目,需要在现有React Native应用里接入鸿蒙设备能力。翻了一圈资料,发现能直接参考的实践不多,大部分还停留在“跑通Demo”的阶段。这周把整个链路跑通了,从鸿蒙开发基础到RN项目里挂载鸿蒙原生组件,踩了不少坑。这篇文章不打算讲高深架构,只把从零到一的过程和关键决策讲清楚,给你一份能直接照着做的参考。
先说说项目背景。我们原本有一款基于React Native的跨端App,已经覆盖iOS和Android,业务上需要扩展到鸿蒙设备。完全用ArkTS重写一遍成本太高,团队也没有这个人力储备;但如果只做一套WebView套壳,体验又跟不上。于是我们选了一条折中路线:保留RN为主框架,把鸿蒙特有的能力封装成原生组件,通过桥接暴露给JS层调用。这样一来,JS业务逻辑可以大规模复用,原生能力又能按需补齐。
这个需求的核心其实和“React Native开发鸿蒙组件”这个标题完全对应:你既要有能力理解鸿蒙开发的基础知识,又要知道怎么把鸿蒙组件集成到RN工程里。说实话,鸿蒙OS是一个分布式操作系统,它和iOS、Android最大的区别不只是UI框架不同,还有分布式设备协同、跨端流转这些能力。如果没有这一层认知,你很可能把鸿蒙当成另一个Android来做,后面会走很多弯路。
这个方向适合谁参考?如果你正打算把RN项目迁移到鸿蒙,或者想了解鸿蒙自定义组件与RN集成的技术可行性,这篇文章都能给你一个比较完整的参考。如果你只是听说鸿蒙热,想先观望,这篇文章也能帮你评估一下投入产出比。
1.2 技术路线选择:RNOH和WebView方案怎么取舍
现在要做RN加鸿蒙,市面上主要就两条路线。
第一条是使用OpenHarmony社区维护的React Native for OpenHarmony,有些人简称RNOH。它把RN的渲染层落在了ArkUI上,JS逻辑还是RN那套,但原生模块和原生组件需要针对鸿蒙重新实现。这也是目前最接近“RN原生活动”的路线,热更新、调试工具链都能用起来。
第二条是WebView方案,在鸿蒙应用里内嵌一个WebView,加载RN打包后的静态页面。这个方案一次性成本低,但交互能力和性能都受限,适合快速验证,不适合有复杂原生依赖的正式项目。如果你只是做一个简单展示页,WebView完全可以顶上;但一旦涉及摄像头、分布式流转、系统级推送,WebView的桥接成本会变得非常高。
我们最终选了RNOH。原因很直接:App里已有大量RN生态组件,如果走WebView,这些组件全废掉,还要处理离线包和JSBridge兼容问题。RNOH至少能复用JS层代码和大部分纯JS组件,真正需要重写的主要是依赖原生API的组件。
但RNOH有一个现实问题:版本跟进速度比社区慢,而且对鸿蒙新特性的封装并不全。举个实际例子,Android上获取设备分布式文件路径,直接调系统API就行;在RNOH里,目前还没有现成的Module,需要自己用ArkTS写一个原生模块桥接。我在实际开发中也验证了这一点,很多“官方文档没写”的能力,反而需要自己动手。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 鸿蒙开发基础:快速扫盲
2.1 ArkTS语言:不用重学,但要改几个习惯
如果你写过TypeScript,ArkTS的上手成本其实很低。它的语法以TS为底座,但做了两层收紧:一是禁止用any,二是要求UI组件的状态变量必须用装饰器标注。这两点对老TS开发者来说都不难,但确实需要适应。
最常见的几个装饰器,我列在下面,这些都是后面写组件时一定会碰到的:
- @Component:声明这是一个自定义组件。
- @Entry:声明这是页面入口。
- @State:声明组件内部可变状态,状态变了UI自动更新。
- @Prop:父组件传进来的单向数据。
- @Link:双向绑定,父子组件共享状态。
- @Builder:自定义构建函数,用来复用UI片段。
一开始最容易踩的坑是:习惯了在React里定义业务对象用普通class,到ArkTS里如果成员变量没初始化,编译器直接报错。你不一定需要完全重构,但结构体的写法要调整。比如你定义一个任务模型:
typescript复制// 推荐写法:使用interface描述数据结构
interface TaskItem {
id: number;
title: string;
done: boolean;
}
这个在RN里看起来没问题,但在ArkTS里要注意:interface的字段如果有可选性,必须显式标注undefined。如果你把一个字段写成title?: string,在ArkTS某些版本里会要求你补上| undefined,否则编译过不去。
另外,ArkTS对装饰器的使用范围有严格要求:装饰器只能作用于类,不能作用于普通函数。这意味着你没法像写JS那样随手给一个函数挂装饰器。所有回调、状态管理、生命周期钩子都要放在类组件内部写。这个习惯一旦适应,后面开发原生组件会顺很多。
我在项目里用的是DevEco Studio 5.0版本,配套ArkTS 1.2,整体感觉跟TypeScript 4.5差不太多,工程上完全可以接受。如果你之前只写过JavaScript,没碰过TS,那建议先花两天补一下类型系统基础,否则写鸿蒙组件会非常吃力。
2.2 ArkUI声明式UI与组件生命周期
ArkUI是鸿蒙的声明式UI框架,写法和SwiftUI、Flutter有点像。你声明组件树,然后通过状态变量驱动刷新。以下是写一个自定义计数按钮的例子:
typescript复制@Component
struct CounterButton {
@State count: number = 0;
build() {
Button(`点击了 ${this.count} 次`)
.onClick(() => {
this.count++;
})
}
}
这段代码里,count加了@State,点击按钮加1,UI自动刷新。听起来和React的useState挺像,但有个重要区别:ArkUI的状态管理粒度更细,且有内置的联动机制,不需要React那个协调器。换句话说,你改一个状态变量,只有依赖它的UI会刷新,不会引发整棵树重渲染。
组件生命周期主要这几个:
- aboutToAppear:组件即将显示,类似React的componentDidMount。
- aboutToDisappear:组件即将销毁,类似componentWillUnmount。
- onPageShow / onPageHide:页面级生命周期,类似RN的AppState变化。
- build:渲染UI。
开发RN桥接组件时,aboutToDisappear特别重要。如果你在组件里注册了数据监听,一定要在这个回调里注销,否则会出现JS侧回调泄漏,表现为组件反复创建后内存持续上涨。这个坑我们在后面章节还会具体展开。
ArkUI还有一个特性是@Builder,适合把一段重复的UI抽出来复用。比如你有一个列表项要在多个地方展示,可以写:
typescript复制@Builder
DeviceListItem(deviceId: string) {
Row() {
Text(deviceId)
Image($r('app.media.device_icon'))
}
}
这个和React里抽一个函数组件很类似,但语法上更贴近模板。对于从RN过来的开发者,这种混合写法需要一点时间适应,但它比JSX少一些嵌套,可读性反而更高。
2.3 鸿蒙的模块与依赖管理:ohpm、HAR和HSP
鸿蒙的工具链里有ohpm命令,类似npm。装依赖、发布库都是用它。项目结构上,一个鸿蒙工程会有oh-package.json5声明依赖,需要下载依赖时用ohpm install。
模块分两种:HAR(HarmonyOS Archive)和HSP(HarmonyOS Shared Package)。简单理解,HAR相当于npm包,被引用时会打包进宿主应用;HSP支持运行时共享,体积优化。在RN集成场景下,我们通常需要打一个HAR去给RN宿主项目引用,因为RNOH本身就是一个HAR形态的依赖。
这里有个容易踩的坑:不同的鸿蒙版本对API的兼容口径不一样,API 9和API 12差别很大。你引用三方库时,一定要看它声明支持的最低API版本,否则编译报错或者运行时崩溃。我见过一个项目直接引用了API 12的特性,但目标设备还是API 9的系统,结果在真机上崩了一整天。
另外,ohpm仓库在国内网络环境下基本能直接访问,但如果你在公司内网,可能需要配置镜像源。配置文件在~/.ohpm/.ohpmrc,可以把registry地址换成内网镜像。这个细节不处理的话,依赖同步会一直卡在等待响应状态。
我们后面章节演示的自定义组件,用的是Stage模型下的AbilityStage加自定义组件导出方式,这正是当前鸿蒙应用的主流形态。理解Stage模型和以前的FA模型区别,对开发RNOH桥接组件会很有帮助,简单说就是页面和能力的生命周期更清晰了,也更容易做模块化。
3. 搭建React Native与鸿蒙的集成环境
3.1 工具链与版本配套:先把“地基”打好
先交代一下我最终跑通的版本组合。这个组合不敢说最优,但在当前时间点多数组件都兼容:
| 组件 | 版本建议 | 备注 |
|---|---|---|
| DevEco Studio | 5.0及以上 | 需要支持HarmonyOS NEXT |
| HarmonyOS SDK | API 12+ | 与RNOH的要求匹配 |
| Node.js | 18 LTS及以上 | 低于16会有兼容问题 |
| React Native社区版 | 0.72及以上 | RNOH对标版本 |
| @react-native-oh/react-native-harmony | 与RN版本对应 | 核心库 |
| ohpm | 随DevEco内置 | 鸿蒙包管理 |
为什么单独提Node版本?因为RNOH的脚手架脚本依赖Node的某些API,在Node 16下跑会报语法错。我一开始在旧机器上直接用Node 14,初始化就失败了,后来换到18才通过。如果你公司用nvm管理Node版本,记得先切到18及以上再执行脚手架命令。
安装DevEco Studio时,建议勾选HarmonyOS SDK组件、模拟器和hdb工具包。hdb是鸿蒙的开发调试工具,类似Android的adb。但要注意,从HarmonyOS 4.2开始,hdb的使用方式有所调整,我们后面调试章节会细说。
还有一点容易被忽略:RNOH对C++编译工具链有要求,Windows上需要安装Visual Studio的C++生成工具,macOS上需要Xcode Command Line Tools。如果你在编译时看到“cxx bridge”相关报错,八成是C++工具链没装完整。
3.2 初始化RN项目并叠加鸿蒙工程
RNOH目前的推荐流程是先创建一个标准RN项目,再通过脚手架叠加鸿蒙工程。以react-native 0.73为例:
bash复制npx react-native@0.73.0 init RNHarmonyDemo --version 0.73.0
cd RNHarmonyDemo
npx @react-native-oh/react-native-harmony@latest init
init命令会帮你生成harmony目录,并在里面放一个能编译的鸿蒙工程。这时候不要急着改业务代码,先跑一遍确认基础链路通。
打开DevEco Studio,选择“打开本地工程”,定位到项目里的harmony目录。首次打开会自动同步依赖,如果卡在等待同步,可以把网络检查关掉:File > Settings > Search for network,取消相关代理校验。同步完成后,尝试用模拟器运行。能跑出RN首页,说明你的环境没问题。
初始化完成后,我强烈建议先把harmony/entry/src/main/ets/entryability/EntryAbility.ets打开,看看它加载的bundle路径。默认情况下,RNOH会使用entry/src/main/resources/base/media/index.bundle。如果你改了RN入口文件名,这里也要同步改,不然会黑屏或白屏。
3.3 Metro与DevEco联调:热更新怎么配才顺
RN开发依赖Metro做热更新。跑了鸿蒙工程后,App启动时会尝试加载JS bundle。在调试模式下,它会去请求Metro服务,所以你需要先在命令行启动Metro:
bash复制npm start
然后打开DevEco的模拟器或者真机运行。如果页面一直空白,先看两个地方:一是Logcat里的网络请求有没有报连接8081失败,二是确认Metro在运行且端口没被占用。
我在第一次联调时遇到一个问题:模拟器里能连接Metro,但真机怎么都连不上。后来发现是DevEco的调试模式默认把Metro地址写成了localhost,真机访问不到。解决方法是把Metro地址改成电脑的局域网IP,然后在DevEco的构建配置里覆盖这个变量。
多提一句:如果你是公司内网环境,有代理拦截,Metro的热更新可能会断断续续。解决办法是在metro.config.js里调整blockList,把不需要监听的大目录排除掉,同时确保网络是通的。这个经验直接关系到开发效率,早处理早舒服。
整体来说,RNOH的联调链路比Android侧多了一层鸿蒙工具链。排查问题思路要先分清楚是哪一端出了问题:是JS bundle没加载出来,还是鸿蒙原生渲染失败,还是Metro通信断了。别一上来就怀疑业务代码,那样容易白费时间。
4. 开发鸿蒙原生组件并桥接到React Native
4.1 在鸿蒙工程里实现自定义原生UI组件
我们最终要实现的组件是一个“分布式设备列表选择器”,点击后弹出当前网络里可用的鸿蒙设备,选择后把设备ID回传给RN。这个功能如果纯用JS实现,根本没有权限访问分布式设备发现能力,必须走原生。
在鸿蒙工程中先建一个ArkTS文件,声明组件:
typescript复制@Component
export struct DevicePickerView {
@Prop deviceList: string[] = []
@State selectedDeviceId: string = ''
private onDeviceSelected?: (deviceId: string) => void
aboutToAppear() {
// 在这里初始化分布式设备发现
this.startDiscovery()
}
build() {
Column() {
Text('选择目标设备')
List() {
ForEach(this.deviceList, (deviceId: string) => {
ListItem() {
Text(deviceId)
.onClick(() => {
this.selectedDeviceId = deviceId
this.onDeviceSelected?.(deviceId)
})
}
})
}
}
}
}
这不是一个完整的生产实现,但包含了三个关键点:@Component导出、@Prop接收RN传来的数组、回调通过可选函数类型暴露给外部。注意,ArkTS里组件不能直接导出普通class方法,回调必须通过属性注入。
我看到很多开发者第一次在鸿蒙里写组件,会习惯性地把获取设备列表的逻辑写在build里,这在ArkUI里是非常糟糕的写法。build方法在状态变化时会频繁触发,而设备发现只需要在组件出现时执行一次。正确的做法是放在aboutToAppear里,否则会出现重复发现设备、界面卡顿的问题。
这里还要提醒一下:在ArkTS里不能直接使用JS的Math.random之类吗?其实可以,ArkTS支持大部分标准JS语法。但是有些API受限,比如动态访问对象的任意属性,编译器会要求你先定义好类型。所以如果你在开发中遇到“Cannot access property”的编译报错,多半是对象结构没有被显式声明,而不是代码逻辑问题。
4.2 如何让RN侧识别鸿蒙组件:注册与导出
RNOH的桥接思路和Android上写Native组件很类似。你需要实现一个类,继承描述器并注册组件。以我们用的0.72版本为例,官方推荐的是新的Component Descriptor API:
typescript复制@RegisterComponent(
'DevicePickerView',
() => DevicePickerView,
{
arktsComponent: true,
}
)
export class DevicePickerViewDescriptor extends ViewComponentDescriptor<DevicePickerView> {
onReceiveCommand(instance: DevicePickerView, command: string, args: any[]) {
// 处理JS下发的命令
}
onPropChanged(instance: DevicePickerView, propName: string, value: any) {
// 处理JS传来的属性变化
}
}
注册完成后,在RN侧还需要写一个配套的Component,让JS能正常渲染:
typescript复制// JS侧
import { requireNativeComponent } from 'react-native';
const DevicePickerView = requireNativeComponent('DevicePickerView');
export default DevicePickerView;
到这里,JS就能这样使用了:
typescript复制<DevicePickerView
deviceList={devices}
onDeviceSelected={(id) => setSelectedId(id)}
/>
这个流程看起来简单,实际坑很多。最大的坑是:组件名必须全局唯一,且注册名和JS侧requireNativeComponent的名字必须完全一致。如果改了注册名,忘了改JS侧,会报“Cannot find native component”错误,而且错误信息非常隐蔽,只在原生日志里能看到。
第二个坑是:onReceiveCommand和onPropChanged这两个方法,如果你不重写,RNOH会有默认实现。但默认实现不会帮你做类型转换,例如JS传过来的数字数组,在ArkTS侧可能变成Array<number>或者Array<any>,如果你在代码里用string[]去接,就会跑出类型不匹配的错。我的建议是:在桥接层显式做一次类型转换,不要依赖隐式行为。
4.3 JS侧调用与传参细节:属性事件双向通信
RN和鸿蒙交互通常有两种模式:一种是属性传递,适用于数据的单向流动;另一种是事件回调,适用于异步状态返回。上面的例子就是两者混合。
属性传递时,RNOH会自动把JS的object转换成ArkTS可识别的类型。但要注意几件事:
- 数组必须明确元素类型,
@Prop deviceList: string[]比@Prop deviceList: Array<any>稳定得多。 - 布尔值在ArkUI里如果要触发刷新,必须用@State修饰。@Prop虽然也能拿值,但不会驱动UI更新,这个和React里props的语义不太一样。
- 函数属性不能直接作为@Prop传递,通常通过外部容器类的回调方法注入。
事件回调方面,我建议不要在组件里直接调RN的global回调,而是定义一个代理类,让链路更清晰,也方便做内存回收:
typescript复制export class DevicePickerController {
private jsCallback?: (deviceId: string) => void;
setCallback(cb: (deviceId: string) => void) {
this.jsCallback = cb;
}
notifySelected(deviceId: string) {
this.jsCallback?.(deviceId);
}
}
然后通过Component的方式注册给JS侧,这样回调链路可控,排查问题的时候也能更清楚地看到是JS层还是原生层出了问题。
这里很多人会问:为什么不做成TurboModule?TurboModule适合的是方法调用,比如“发现设备”“断开设备”,而组件适合的是UI渲染加交互。我们的场景是UI组件,所以选组件桥接是合适的;如果只是把设备能力暴露成API,那用TurboModule更省事。我最终项目里两种都用了:UI交互走Component,能力API走TurboModule。这样各取所长。
4.4 桥接过程中的数据格式与类型安全
跨语言桥接最容易出的问题就是数据格式不一致。RN侧传一个对象过来,鸿蒙侧接收时,如果你没有定义好interface,编译器可能直接报错。所以我建议在桥接层单独建一个类型定义文件,把JS侧和ArkTS侧共享的数据结构都写清楚。
typescript复制// 鸿蒙侧
export interface DeviceInfo {
deviceId: string;
deviceName: string;
deviceType: number;
isOnline: boolean;
}
JS侧对应:
typescript复制export interface DeviceInfo {
deviceId: string;
deviceName: string;
deviceType: number;
isOnline: boolean;
}
两边的字段名、类型必须一致。特别是数字类型,ArkTS里number同时覆盖整数和浮点数,但在分布式设备ID场景下,iOS的ID可能是短横线格式,鸿蒙的ID可能是纯数字字符串,这个差异要在JS侧做兼容,别把类型校验放在原生层。
如果你在调试时发现JS传参后UI没反应,优先排查是不是@State、@Prop装饰器加漏了。ArkUI对状态驱动UI的依赖非常强,不加@State它不会主动刷新。这个和React Hooks的依赖数组有点类似,但ArkUI更严格:不是“你声明了才更新”,而是“你没声明一定不更新”。
5. 调试、白屏与常见问题排查
5.1 hdb调试与无线调试:鸿蒙开发者的日常工具
HarmonyOS 4.2以后,官方调试工具从hdc改成了hdb。在设备上开启开发者模式后,可以先用USB连接,然后执行:
bash复制hdb devices
如果能看到设备,说明基础连通正常。接下来开启无线调试:
bash复制hdb tcpip 5555
hdb connect <device_ip>:5555
无线调试配好后,就可以丢开数据线,在电脑上直接看日志了。我要强调一点:HarmonyOS的开发者模式入口和安全设置在不同版本上不一样,4.2之后还需要在“应用”里对被调试的App开启“可调试”权限,不然hdb connect成功后也抓不到应用日志。
排查问题最常用的是:
bash复制hdb shell hilog
hilog是鸿蒙的日志系统,类似logcat。可以按进程过滤:
bash复制hdb shell hilog -T RNOH -e "Error"
这个命令能过滤出RNOH标签下的错误信息。做RNOH调试的时候,这个标签要比看console.log高效得多。我经常同时开两个终端,一个跑Metro,一个跑hilog过滤,这样业务报错和原生报错能同时看到。
还有一个技巧:如果你发现hilog输出太多,可以先执行hdb shell hilog -r清空缓存,再复现问题,这样日志里只有你这次操作的记录,定位起来快很多。
5.2 RN启动白屏排查思路:按顺序逐层定位
RN启动白屏是搜索热词里出现最多的,我在RNOH里也遇到两次,一次是开发调试阶段,一次是打正式包阶段。排查顺序我建议是:
- 先确认bundle是否加载成功。在日志里搜索“Loading JS bundle”或者“bundle url”,如果没看到这个日志,说明Metro地址配错了或网络不通。
- 再确认渲染层是否报错。RNOH中,ArkUI渲染层如果崩了会打印“Fatal Exception”,这时需要看hilog。
- 最后确认JS业务代码有没有抛异常。把入口文件里的console.error替换成日志输出到原生,能定位到JS层的报错。
我一个具体的案例:打正式包后白屏,原因是release包默认从本地assets加载bundle,但RNOH的打包脚本没有把bundle文件拷贝到鸿蒙工程的assets目录。解决方法是先执行RN的打包命令生成bundle,然后执行鸿蒙工程的编译命令,顺序不能反。
bash复制npx react-native bundle --platform harmony --dev false --entry-file index.js --bundle-output ./harmony/entry/src/main/resources/base/media/index.bundle
这个命令生成bundle后再去DevEco里编译。如果少了这步,正式包就会白屏。开发模式因为走Metro,反而不会出这个问题。
另外,白屏也可能是因为ArkUI的渲染容器没有拿到高度。检查一下最外层组件是否设置了width('100%').height('100%')。如果RNOH的容器默认是wrap_content,在有些设备上会撑不开,表现为白屏或只有一小块区域显示。给根节点加一个明确尺寸,问题立刻就好。
5.3 高频问题速查:从环境到运行时的避坑清单
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| 初始化脚手架报错 | Node版本过低 | 升级到Node 18+ |
| 真机连不上Metro | localhost配置错误 | 改成电脑的局域网IP |
| 组件传参后UI不刷新 | 属性缺少@State | 容器状态变量加上装饰器 |
| 回调泄漏内存上涨 | 未在aboutToDisappear注销 | 生命周期里做反注册 |
| 编译报“API不存在” | 三方库API版本不匹配 | 检查库声明的最低API版本 |
| 打正式包白屏 | bundle未拷贝到assets | 先打bundle再编鸿蒙工程 |
| hilog看不到应用日志 | App未开启可调试权限 | 在应用设置里开启调试权限 |
| 真机无法安装release包 | 签名证书未配置 | 在DevEco里配置自动签名 |
这些问题在官方文档里分散在各处,我按遇到频率排了序,基本覆盖了我实践中80%的问题。如果你遇到表格里没有的情况,建议先用hilog抓一段完整报错,再按“JS层—桥接层—原生层”的顺序去定位,基本都能找到原因。
6. 更进一步:性能优化与团队落地建议
6.1 包体积和首屏性能:HSP拆分与bundle瘦身
除了跑通,我们还需要考虑性能与包体积。RNOH叠加一个鸿蒙原生工程,体积天然不小。我们最终用HSP做了动态共享,把公共框架拆出来,主包体积压缩了约18%。如果你的应用对体积敏感,这个方向值得投入。
具体做法是:把RNOH核心库和业务公共库拆成HSP,宿主App运行时动态加载。这样多个应用或者多个模块可以共享同一份原生代码,升级框架时也不用重新安装整个App。
首屏性能方面,分布式能力是鸿蒙的差异化亮点。用RNOH做开发最大的优势不是复用RN代码,而是能低成本接入这些系统能力。把设备发现、流转、数据共享封装成原生Module后,JS侧调用非常简单,几乎和普通事件一样。但要注意,设备发现不是瞬时操作,建议在aboutToAppear里异步初始化,不要阻塞UI渲染。React Native启动白屏这个问题,在半数情况下也和主线程被长时间占用有关。
如果你发现首屏渲染总是白屏,除了检查bundle,还可以看看是不是有大量的同步操作阻塞了UI线程。把数据请求、设备发现都改成异步,同时把首页尽量拆小,能明显改善启动速度。
6.2 工具链和团队协作实践建议
团队如果决定要试,我建议先用一个低频业务做试点,把通信链路和打包流程跑稳,再逐步替换核心页面。不要一上来就大范围迁移,否则团队会被报错信息淹没。
开发工具方面,现在很多团队在用AI辅助IDE,比如Trae、Copilot之类的。这些工具对React Native的代码补全已经很成熟,但对鸿蒙特定API的支持还有限。你可以让AI帮你写TS层面的业务代码,但涉及ArkUI装饰器、分布式能力调用时,还是要对照官方文档做校验。AI生成的桥接代码经常漏掉装饰器,编译时才会暴露。
还有一点值得注意:RNOH的版本迭代很快,但社区文档更新不一定同步。建议在package.json里锁定RNOH的精确版本,不要用^范围匹配。否则某天执行npm install,可能自动拉到一个不兼容版本,整个工程编译失败。锁版本能减少这类意外。
我自己的实际体会是,RN加鸿蒙这条路现在还在早期,工程化方面确实有坑,但方向是对的。分布式能力、跨端流转、原子化服务这些特性,如果能通过RNOH低成本接入,对业务来说价值很大。关键是要有耐心,先把环境配稳,再逐步啃原生桥接的细节。踩过一轮坑之后,后面再做类似功能,速度会快很多。
