如果你的团队已经用 React Native 开发了核心业务 App,现在产品经理突然告诉你,需要适配 HarmonyOS 生态,你第一反应多半不是开心,而是头皮发麻:难道要把已经写好的几百个页面全部用 ArkUI 重写?别急着否定,先想清楚一个关键问题——你真正需要的是让 React Native 在鸿蒙上跑起来,还是需要让鸿蒙原生组件为你所用?
“在 React Native 中开发鸿组件”这个需求,本质上就是在回答上面这个问题:React Native 负责业务逻辑和页面壳,鸿蒙原生组件负责系统级 UI 和硬件交互,两边通过桥接层协同。它既不是 React Native 向鸿蒙妥协,也不是鸿蒙向 React Native 靠拢,而是把双方的强项拼在一起。这篇文章我不会去讲怎么用 ArkUI 重写一套鸿蒙应用,而是把我实际在 React Native 工程里集成和开发鸿蒙组件的完整经验拆给你看,包括环境怎么搭、桥接原理是什么、一个组件从 ArkTS 侧到 React Native 侧怎么落地,以及调试和排查链路里最常见的几个大坑。
1. 为什么要在 React Native 里嵌鸿蒙原生组件:先分清必要与多余
1.1 先搞清楚“鸿组件”到底指什么
很多人一听“鸿组件”,第一反应是:把 RN 页面里的按钮、列表、弹窗全部换成鸿蒙原生的?这是一个很危险的误解。鸿蒙原生组件并不等于 ArkUI 官方组件库里的那些基础控件,而是指能够在 HarmonyOS 上运行的、由 ArkTS 声明式语法或者偏底层能力构建出来的原生视图单元和功能模块。
举个例子。你有一个电商 App,商品列表用 RN 的 FlatList 实现完全没问题,滚动性能在优化之后也能接受。但是如果你要做一个城市级联动选择器,或者一个支持跨设备流转的卡片组件,或者需要调用系统安全控件完成人脸识别,那 RN 生态里现成的组件就很难满足。这时候你需要的,恰恰是鸿蒙侧的原生组件和能力。
所以我的判断标准很简单:凡是 RN 自己能干得不错的事情,不要碰鸿蒙原生;凡是 RN 干不了、干不好、或者干起来成本极高的事情,才值得做成鸿组件。真正需要鸿组件的场景,往往是那 20% 的“长板”场景,比如:
- 复杂手势交互,像多指旋转、压感触摸这类需要走系统级事件通道的
- 系统级 UI,像安全输入框、系统分享面板、隐私弹窗
- 分布式能力,像多设备协同、跨端拖动、原子化服务卡片
- 高性能渲染,像长列表预加载、复杂动画的逐帧驱动
1.2 三条技术路线的对比
我在真正动手之前,把团队可能走的路线全部摆出来对比了一轮,核心就三条。
第一条,直接把 RN 工程改成纯 ArkUI 重写。这条路看着最“正统”,但成本高到离谱:一套已经调试好的业务逻辑,全部用 ArkTS 再来一遍;后续每一次需求变更都要双端同步维护,React Native 生态里那些成熟的包也全部用不上。
第二条,让 React Native 直接跑在鸿蒙上,业务层全部用 RN 的 JS/TS 写,不做任何鸿蒙原生适配。这条路的可行性比前几年高了很多,因为社区里已经有人在推动 React Native for OpenHarmony 的方向,但是问题在于:你只是把 JS 业务搬到了鸿蒙设备上,很多系统级能力、交互细节、设备硬件能力仍然够不着。
第三条,就是本文的主题:主体工程保持 React Native,按需把鸿蒙原生组件桥接进来。业务页面继续用 RN,遇到真正需要原生能力的位置,才从鸿蒙侧写一个组件,再暴露给 RN 调用。这条路前期需要一点桥接层的基建工作,但是长期看维护成本最低,而且两边团队的边界非常清楚。
三条路线的对比,我放到了一张表里:
| 路线 | 开发成本 | 性能上限 | 维护成本 | 生态复用 | 适合场景 |
|---|---|---|---|---|---|
| 纯 ArkUI 重写 | 极高 | 最高 | 双端并行,长期偏高 | 鸿蒙生态 | 全新独立鸿蒙 App |
| 纯 RN 跑鸿蒙 | 中等 | 中,受限于 RN 桥接能力 | 低 | React Native 生态 | 业务简单、原生依赖少 |
| RN + 鸿组件桥接 | 中高(前期基建) | 高,按需原生优化 | 中,边界清晰 | 双端生态 | 已有 RN 工程、需要鸿蒙原生能力 |
1.3 常见的反面案例
我见过不少团队在“要不要做鸿组件”这件事上走了弯路。有一种是过于激进,把 RN 项目里所有自定义 UI 都往鸿蒙侧塞,结果桥接层代码比业务代码还多,每次版本升级光适配桥接层就要好几天。另一种是过于保守,明明有些功能在 RN 侧实现会卡成幻灯片,仍然坚持纯 RN 方案,最后用户体验一塌糊涂。
我自己踩过的比较典型的一次,是做一个复杂的手势涂鸦编辑器。最初坚持用 RN 的 PanResponder 做,结果笔触延迟明显,缩放旋转手势在低端机上直接掉帧。后来老老实实把涂鸦画布写成了鸿蒙原生组件,手势走系统事件通道,性能问题直接消失。但另一个选择器组件,我图省事也做成了鸿组件,结果发现 RN 侧实现只要多套一层 FlatList 就够,桥接反而成了纯额外负担。
这个问题的核心结论是:做鸿组件之前,先做减法。把需求列表里每个功能都过一遍,先问 RN 自己能不能干,能干的坚决不做;不能干的,再评估鸿蒙原生是不是最优解;两个问题都确认了,才进入开发阶段。
2. 环境准备:DevEco Studio、RNOH 脚手架与调试链路的版本匹配
2.1 工具链版本匹配:先锁版本,再谈开发
在 React Native 工程里开发鸿蒙组件,最怕的不是写代码,而是环境版本错位把一整天时间烧掉。React Native 本身迭代就快,鸿蒙开发工具链也在不断更新,两边的版本对不上,轻则编译报错,重则运行时崩溃且日志完全不可读。
我的建议是:不要自己手工拼版本,直接以 React Native for OpenHarmony(社区里一般简称 RNOH)官方模板和脚手架为准,先把官方 Sample 跑起来,再逐步替换成自己的业务代码。以我当前使用的版本组合为例,大概是这样的:
| 组件 | 版本建议 |
|---|---|
| Node.js | 18 及以上 |
| DevEco Studio | 5.0 及以上(对应 API 12+) |
| React Native | 0.72 及以上(以 RNOH 支持版本为准) |
| RNOH 脚手架 | @react-native-oh/react-native-harmony 最新稳定版 |
| HarmonyOS SDK | API 12 及以上 |
这个表不是死的,因为 RNOH 的版本迭代速度确实快,新版本可能支持更高版本,但原则是一致的:先用脚手架生成一个干净的模板工程,模板里锁定的版本就是经过验证的组合,不要单独升级其中一个组件。
2.2 从零创建一个 RN + 鸿蒙工程
环境搭起来其实不算复杂,但步骤有顺序要求。我整理了一下实际操作路径。
第一步,创建 RN 工程。这一步和平时创建 React Native 项目没有任何区别,我一般直接用官方 CLI:
npx @react-native-community/cli init RNHarmonyDemo cd RNHarmonyDemo第二步,把鸿蒙侧工程通过脚手架接入。RNOH 提供的脚手架命令会在 RN 工程里生成一个 harmony 目录,这个目录本质上就是一个完整的 DevEco Studio 工程。我用的命令大致是:
npm install @react-native-oh/react-native-harmony --save-dev npx @react-native-oh/react-native-harmony init执行完之后,你的 RN 工程结构里会多出一个 harmony 文件夹,里面有 entry、hvigorfile、oh-package.json 等等。打开 DevEco Studio 时直接选择这个 harmony 目录作为工程根目录就能加载。
第三步,验证链路。先用 DevEco Studio 打开 harmony 工程,把一个真实的鸿蒙设备连接上电脑(模拟器也可以,但真机更接近线上环境),然后直接运行。如果这步能跑出一个加载了 RN bundle 的页面,说明环境基本通了。
2.3 真机调试链路:hdb、无线调试与签名配置
很多新手卡在“工程装不到真机上”。这里面有三件事必须提前完成。
第一件事,开发者模式。鸿蒙手机里进入“设置 - 关于手机”,连续点击版本号进入开发者模式,然后打开 USB 调试。如果你用的是 HarmonyOS 4.2 及以上系统,还需要在开发者选项里打开“无线调试”开关,因为有时候真机连着电脑的线不稳定,无线调试更省心。
第二件事,命令行工具。鸿蒙的调试工具现在叫 hdb(HarmonyOS Debug Bridge),早期资料里叫 hdc,两者本质上是同一个东西的演进。把 hdb 配置到 PATH 之后,先用有线方式连上设备验证一下:
hdb list targets如果能看到设备序列号,说明连接成功。然后开无线调试,把手机和电脑放到同一 Wi-Fi 网络下,在手机无线调试界面里拿到 IP 和端口,执行:
hdb tconn 192.168.x.x:5555这条命令建立无线连接之后,就可以拔掉数据线了,后续的日志抓取、应用安装都走无线通道。
第三件事,签名配置。鸿蒙应用安装到真机必须要签名,DevEco Studio 里可以用华为账号的自动签名,也可以配本地调试签名。我建议直接用自动签名,省事,而且调试期完全够用。唯一要记住的是:换电脑或者换设备之后,需要重新登录授权,不然签名失效会报错。
环境这块最后再说一个实用技巧:先跑官方 Sample,再动自己的代码。很多人环境配好了就急着把业务代码往工程里贴,结果根本分不清报错是环境问题还是业务问题。先跑通一个官方示例页面,确认 Metro、bundle 加载、原生侧日志全部正常,再开始业务开发,排查问题的范围会小很多。
3. 桥接原理:ArkUI 组件树如何映射到 React Native 虚拟 DOM 并完成双向通信
3.1 React Native 在鸿蒙上的整体架构
要理解“怎么开发鸿组件”,光会写代码不够,得先把桥接原理吃透。React Native 本身不是把 JS 代码翻译成原生控件,而是通过虚拟 DOM 和原生渲染树做映射。在鸿蒙上,这条链路变成了:JS/TS 业务代码 → React Native 的 C++ 渲染引擎(Fabric) → 鸿蒙原生 ComponentView → ArkUI 节点。
这个架构的好处是,React Native 的跨端逻辑可以完全复用,鸿蒙侧只需要实现统一的原生视图接口,就能把 ArkUI 组件“塞”进 RN 的渲染树里。也就是说,你写一个鸿组件,本质上不是“在 RN 里包一个 ArkUI 页面”,而是“把 ArkUI 的一个节点当成 RN 的一个原生视图来渲染”。
3.2 NodeContainer:把 ArkUI 组件挂进原生视图容器
ArkUI 的声明式组件,比如 Text、List、Stack 这些,正常情况下是写在 @Component 结构体里,由系统统一渲染的。但如果这个组件要交给 React Native 渲染,就需要一个“容器”把 ArkUI 的渲染节点暴露出来。这个容器就是 NodeContainer,配合 NodeContent 使用。
你可以把 NodeContainer 理解成一个画框,NodeContent 是画框里的画芯。鸿蒙侧的 ArkUI 组件通过 NodeContent 创建节点,节点挂到 NodeContainer 上,NodeContainer 作为一个原生视图被 RN 侧引用。这样的话,ARkUI 组件的全部渲染逻辑和交互逻辑都保持原样,RN 只是“看着”这个容器视图,把它当成一个不透明但可交互的原生 UI。
具体到代码层面,RNOH 要求鸿组件对应类继承 ComponentView,并且重写 create 方法,让系统能通过描述符创建实例。鸿蒙侧的 NodeContainer 就创建在这个 ComponentView 里。
3.3 双向通信协议:属性、事件、命令
组件挂上去了,接下来就是通信。React Native 和原生组件之间的交互模型一共三种:
第一种是属性传递,方向是 React Native → 鸿蒙。RN 侧渲染组件时传入的 props,会通过 updateProps 方法同步到鸿蒙侧。比如 RN 传了一个 selectedIndex 数字给滚轮组件,鸿蒙侧就在 updateProps 里把这个数字取出来更新 UI。
第二种是事件回调,方向是鸿蒙 → React Native。用户拖动滚轮,鸿蒙侧检测到索引变化,通过事件机制把这个变化发回 RN。RN 侧对应监听 onValueChange 之类的回调,拿到参数后更新业务状态。
第三种是命令调用,方向是 React Native → 鸿蒙,但需要在特定时机触发。比如 RN 侧要主动让滚轮跳到某个位置,可以通过命令通道发一个指令给鸿蒙侧,鸿蒙侧在接收端执行对应方法。
通信协议在代码层面怎么落地,我在下一章用完整的组件例子来讲,这里先把模型搞清楚。模型清楚了,后面写代码就是套模板的事。
3.4 为什么新架构不直接操作 View 树
有 React Native 经验的朋友可能会有疑问:在 Android 上写原生组件,经常是继承一个 ViewGroup 然后操作子 View,鸿蒙这边为什么不是直接操作 ArkUI 组件树?
原因在于 ArkUI 的渲染机制和 Android View 体系差别很大。ArkUI 的声明式组件是由后端渲染引擎统一管理的,开发者拿不到一个类似 Android View 的强引用去手动 addView。所以鸿蒙侧才会提供 NodeContainer 这种容器机制,把声明式组件的生命周期和渲染托管给系统,开发者只需要在容器层面做桥接。
这一点理解了,后面看到代码里只有一个“容器 + 创建节点”的逻辑,就不会觉得奇怪了。这恰恰是鸿蒙组件桥接和 Android/iOS 原生组件桥接最大的不同。
4. 从零实现一个循环滚轮组件:ArkTS、桥接层、注册与 React Native 侧调用
4.1 为什么拿滚轮组件举例
聊完原理,直接上一段完整的实现。我用“循环滚轮”作为示例,原因有三个:一是循环滚轮在电商、外卖、日期选择这类 App 里出现频率极高,二是 React Native 社区里现成的滚轮组件在性能和手势体验上普遍一般,三是它非常适合演示 ArkUI 侧 UI、事件回调、属性同步三个核心环节。整个链路走通之后,其他鸿组件基本就是复制这个骨架。
4.2 鸿蒙侧:用 ArkTS 实现循环滚轮 UI
先写鸿蒙侧的声明式组件。这里做一个简化的循环滚轮,核心是一个 List,数据无限循环,用户滑动停止后通过 onScrollIndex 回调把当前索引抛出去。ArkTS 代码如下:
@Component export struct WheelPickerView { @Prop selectedIndex: number = 0 onIndexChange: (index: number) => void = () => {} private scroller: Scroller = new Scroller() build() { List({ scroller: this.scroller }) { ForEach(this.getLoopData(), (item: string) => { ListItem() { Text(item) .fontSize(20) .width('100%') .height(80) .textAlign(TextAlign.Center) } .width('100%') .height(80) }) } .height(80 * 5) .onScrollIndex((start: number) => { const index = start % this.dataSource.length this.onIndexChange(index) }) } private dataSource: string[] = ['苹果', '香蕉', '橘子', '葡萄', '西瓜'] private getLoopData(): string[] { // 这里通过重复拼接实现循环效果 return Array.from({ length: 5 }).flatMap(() => this.dataSource) } }实际项目里你可能还要处理阻尼、惯性、回弹这些细节,但核心逻辑就是上面这套。注意我这里用了 @Prop 接收 selectedIndex,这意味着外部可以通过属性驱动它更新;onIndexChange 是一个函数类型的回调,外部可以注入事件处理逻辑。
4.3 桥接层:封装成 ComponentView 并注册
UI 组件写好了,但它还不能直接被 React Native 使用。我们需要在鸿蒙侧的库代码里写一个 ComponentView 子类,把刚才的组件挂载到 NodeContainer 上。
export class WheelPickerComponentView extends ComponentView { private nodeContent: NodeContent = new NodeContent() private nodeContainer: NodeContainer = new NodeContainer() private viewModel: WheelPickerViewModel static create(descriptor: ComponentDescriptor): ComponentView { return new WheelPickerComponentView(descriptor) } constructor(descriptor: ComponentDescriptor) { super(descriptor) this.viewModel = new WheelPickerViewModel() this.viewModel.onIndexChange = (index: number) => { this.emitMessage('onValueChange', { index: index }) } this.nodeContainer.attachNodeContent(this.nodeContent) this.nodeContent.createNode( new WheelPickerView({ selectedIndex: this.viewModel.selectedIndex, onIndexChange: this.viewModel.onIndexChange }) ) this.setCustomNode(this.nodeContainer) } updateProps(nextProps: Record<string, any>) { if (nextProps.selectedIndex !== undefined) { this.viewModel.selectedIndex = nextProps.selectedIndex } } }这一段有几个关键点需要说明。
第一,NodeContainer 的创建是在 ComponentView 的构造器里完成的,通过 attachNodeContent 把 NodeContent 挂到容器上,然后再通过 createNode 把 ArkUI 组件创建到 NodeContent 里。这套流程是固定的,区别只在你要创建哪个组件。
第二,WheelPickerView 这个组件在构造时接收了 selectedIndex 和 onIndexChange,所以 ArkUI 侧的事件回调直接就注入到了组件内部。用户滑动滚轮触发 onScrollIndex 后,数据从 ArkUI 组件传到 WheelPickerViewModel,再通过 emitMessage 发给 React Native 侧。
第三,updateProps 是属性同步的入口,React Native 侧传过来的 props 会在这里被接收。我这里只处理了 selectedIndex,实际项目里如果还有其他属性,逐个在这里取并更新到这个 ViewModel 上。
组件类写好之后,还要在库的注册描述里把这个组件声明出来。RNOH 的第三方组件库一般会在 index.ets 里导出组件描述:
export const WheelPicker = { ComponentName: 'WheelPicker', ComponentDescriptor: WheelPickerComponentView, // 其他配置项按需补充 }RNOH 在构建时扫描这些导出,把组件注册到 React Native 的渲染引擎里。这里有个很容易踩的坑:ComponentName 必须和 React Native 侧引用的名字完全一致,大小写都不能差。我在调试时经常因为组件名拼写不一致,RN 侧渲染报找不到原生组件,排查半天才发现是名字对不上。
4.4 React Native 侧:注册并使用组件
鸿蒙侧的桥接层完成之后,React Native 侧的写法就简单了。传统 RN 架构下,用 requireNativeComponent 直接引入即可:
import React from 'react'; import { requireNativeComponent, ViewProps } from 'react-native'; export interface WheelPickerProps extends ViewProps { selectedIndex?: number; onValueChange?: (event: { nativeEvent: { index: number } }) => void; } const NativeWheelPicker = requireNativeComponent<WheelPickerProps>('WheelPicker'); export function WheelPicker(props: WheelPickerProps) { const { onValueChange, ...rest } = props; return ( <NativeWheelPicker {...rest} onChange={(e) => onValueChange?.(e.nativeEvent)} /> ); }核心逻辑就两行:requireNativeComponent 拿到原生组件引用;onChange 事件桥接把鸿蒙侧发来的 onValueChange 转成 RN 侧的事件对象。
如果你用的是 React Native 新架构(Fabric),组件注册会更规范一些,需要结合 codegen 生成类型描述,但整体思路一致:RN 侧通过统一的原生组件协议加载鸿组件,通信链路不变。
4.5 构建与验证
组件代码写完之后,构建验证的流程我建议这样走:
先在 DevEco Studio 里编译鸿蒙工程,确认 ArkTS 侧没有语法错误和链接错误。然后启动 React Native 的 Metro 开发服务器,把 RN 应用跑起来,页面里引入 WheelPicker 组件:
<WheelPicker selectedIndex={2} onValueChange={(e) => { console.log('滚轮选中的索引是:', e.nativeEvent.index); }} style={{ width: 300, height: 400 }} />整条链路如果正常,你应该能看到滚轮渲染在页面上,滑动滚轮时控制台能打印出索引变化。如果页面白屏或者组件不渲染,先别急着改业务代码,去查第 5 章里的排查清单。
5. 实测风险清单:启动白屏、HDB 调试断连与数据不同步的排查链路
5.1 启动白屏:先查 Metro,再查注册,最后查组件内部
“React Native 启动白屏”是社区里问得最多的问题之一,在鸿蒙环境下排查思路和 Android/iOS 基本一致,但多了几个鸿蒙特有的检查点。
白屏的本质是:JS bundle 没有成功加载,或者加载了但原生视图没有渲染出来。我按排查链路重新走一遍,省得你从零开始。
第一步,检查 Metro 是否启动,以及设备/模拟器能否访问到 Metro 端口。React Native 开发模式下,页面内容是从 Metro 拉的,Metro 没启动或者端口不通,页面直接白屏。确认 8081 端口监听正常,同时确认鸿蒙应用中配置的 bundle 地址正确指向你的开发机 IP。
第二步,确认 release 模式下 bundle 是否有打包。如果你跑的是 release 包,RN 的 JS bundle 需要提前打包并放到鸿蒙工程资源目录里。很多人开发模式没问题,一打 release 包就白屏,九成是 bundle 资源没放全。
第三步,检查原生组件注册。如果你的页面里引用了自定义组件,但组件没有成功注册,React Native 渲染时会直接报错,表现就是白屏。日志里通常会有“component not found”或者类似提示。
第四步,单独隔离测试。把页面里所有业务组件都去掉,只保留一个最简单的 View,看能不能渲染。如果能渲染,说明问题出在某一层原生组件;如果连最简单的 View 都白屏,说明是环境或者 bundle 加载问题。这个二分排查法效率极高。
5.2 hdb 调试与无线调试:日志抓取的正确姿势
鸿蒙开发中,最常用的调试工具就是 hdb。这里把常用命令整理一下,都是实际项目里高频出现的。
| 操作 | 命令 |
|---|---|
| 查看设备列表 | hdb list targets |
| 无线连接 | hdb tconn IP:端口 |
| 安装应用 | hdb install 包路径 |
| 启动应用 | hdb shell aa start -a EntryAbility -b bundleName |
| 抓取日志 | hdb shell hilog |
| 过滤 RN 日志 | hdb shell hilog | grep RN |
无线调试模式下,最省心的一点是:手机和电脑连同一个 Wi-Fi,用 hdb tconn 建立连接后,数据线可以拔掉,日志和安装操作全部走无线通道。但有几个注意点,我实际踩过的:
- 手机在无线调试界面显示的 IP 和端口会变化,断连后要重新去看最新值。
- 公司网络如果开了 AP 隔离,无线调试可能连不上,这时候老老实实用数据线。
- 抓日志时不要只 filter RN 关键字,有些原生报错是通过 hilog 的 ERROR 级别打出来的,建议先抓一次全量日志,再逐步收窄范围。
另外,HarmonyOS 4.2 往上,无线调试的入口在“设置 - 开发者选项”里,打开“无线调试”后系统会显示一个端口号,配合使用 hdb tconn 就能建立连接。第一次使用无线调试时,手机上会弹授权确认框,一定要点允许。
5.3 数据不同步:鸿蒙侧改了状态,React Native 侧不刷新
开发鸿组件时我遇到最多的问题就是“数据不同步”,表现形式是:用户在鸿蒙原生 UI 上做了操作,鸿蒙侧状态确实变了,但 React Native 页面的 UI 不刷新。
这个问题的排查链路比较固定。
第一,确认事件有没有发出去。在鸿蒙侧 emitMessage 之前加日志,事件发送后 RN 侧的监听回调里也加日志,两边日志都打印到了,说明通信链路通;有一边没打印,就断在哪一边。
第二,确认事件名和参数名是否匹配。鸿蒙侧发的消息名是 onValueChange,RN 侧监听的 onChange 事件,两者之间需要代码里手动映射。很多不同步问题不是逻辑错,而是事件名拼写不一致。
第三,确认是否真的要驱动 RN 状态更新。有时候鸿蒙侧状态变了,但你不希望 RN 侧整个页面重渲染,就不需要把这个状态同步回 RN。如果你只是需要原生组件内部状态,保持在鸿蒙侧维护就行,不要盲目同步,不然会造成不必要的重渲染和性能损耗。
第四,如果用的是受控属性,比如 selectedIndex 由 RN 侧传入,那么鸿蒙侧内部不能直接改这个值,改了也会被 RN 下一次属性更新覆盖。这种情况下的正确做法是:鸿蒙侧通过事件把变化传给 RN,RN 侧更新自己的 state,再把新值传回鸿蒙侧。受控循环确实绕,但跨端组件的一致性问题,大部分最终都要靠这种单向数据流来兜底。
写在最后:我在实际集成试验中的几点体会
最后说几句不太容易在官方文档里看到的东西。
第一,版本锁定是最大的护身符。React Native 和鸿蒙工具链都在快速迭代,不要追求“所有组件都最新”,而是要锁定一组经过互相验证的版本。我每次换版本,都会出现一些意外问题,而问题解到最后,往往只是某个包的 API 变了。
第二,调试阶段先用最小闭环跑通链路,再填充业务逻辑。我在开发滚轮组件时,第一遍只做了一个不带动画的静态列表,属性、事件、注册全部通了之后,才开始加循环逻辑和动画效果。这样做的好处是,每一步出问题时,排查范围都极其有限。
第三,鸿组件不是越多越好,而是要精准。当你手上有完整的桥接封装之后,会很容易产生“反正封装成本不高,顺手都做了”的冲动。但桥接层每多一层,就多一份维护成本和升级压力。真正合理的状态是:鸿组件保持在一个克制的数量,只在 React Native 确实不够用的位置出现。
从环境搭建到桥接原理,再到一个完整组件的实现和排错,这条链路走一次之后,你会发现“在 React Native 中开发鸿组件”并没有想象中那么神秘。它无非是把跨端开发和原生开发各自的优势拼接起来,用最少的代价,让应用在鸿蒙生态里跑得更舒服。希望这篇拆解能帮你少踩几个坑,把时间花在真正有挑战性的业务上。