【开源鸿蒙跨平台开发学习笔记】Day08:React Native 开发 OpenHarmony —— RN 与原生调用全解析

前言

本次参加开源鸿蒙跨平台开发学习活动,选择了 React Native 开发 HarmonyOS技术栈,在学习的同时顺便整理成一份系列笔记,记录从环境到开发的全过程。本篇作为第八篇,在前几篇文章中,我们已经完成了 React Native 项目在 OpenHarmony 上的环境搭建、基础组件使用、页面路由等内容。

从今天开始,我们进入"跨平台框架最核心的一环"------RN 与原生能力互相调用(双端通信)。

在 OpenHarmony(ArkTS/ArkUI)上集成 React Native 后,我们通常会遇到两类需求:

  1. JS → 原生(ArkTS/Harmony)调用
  2. 原生(ArkTS/Harmony) → JS 调用

这两部分共同构成 RN 新架构(TurboModules + Fabric)的核心通信桥。

我们将从实战角度说明在 OpenHarmony 中如何实现这两类调用,并结合具体代码示例来掌握"跨端通信"的完整方法。

一、RN 与 OpenHarmony 原生通信的整体架构

React Native 新架构(The New Architecture)基于以下能力构建:

  • TurboModule(JS 调用原生能力)

  • JSI(JavaScript Interface)高性能桥接层

  • Fabric UI Layer(跨端组件渲染)

在 OpenHarmony 上,RN 团队已经适配了 RNInstance、TurboModule、DeviceEventEmitter、CppComponentInstance 等桥接能力,使开发者可以:

  • 在 JS 侧无缝调用 ArkTS 或 C++ 原生方法

  • 在 ArkTS/C++ 侧向 JS 发送事件

  • 组件可通过事件上报数据给 JS

  • 原生模块可主动调用 JS Function

理解这些能力后,我们就可以开始实战啦。

二、JS → 原生:使用 TurboModule 调用 OpenHarmony 原生能力

在 RN 新架构中,JS 调用原生采用 TurboModule。

在 OpenHarmony 中也完全支持。

TurboModule 模块的实现流程:

  1. 定义原生模块接口(TypeScript 声明)

  2. 在 ArkTS 或 C++ 中实现对应方法

  3. 通过 TurboModule 注册

  4. 在 JS 侧调用

示例:

TypeScript 复制代码
import { TurboModuleRegistry } from 'react-native';

export interface MyModuleSpec extends TurboModule {
  getSystemInfo(): Promise<any>;
}

export default TurboModuleRegistry.getEnforcing<MyModuleSpec>('MyModule');

然后你就可以在 JS 中直接调用:

TypeScript 复制代码
const info = await MyModule.getSystemInfo();
console.log(info);

如果你需要封装自己的模块,可以参考官方教程《自定义 TurboModule》。

三、原生 → JS:三种通信方式全面解析

OpenHarmony 原生侧(ArkTS / C++)可以通过多种方式向 RN JS 侧发送事件或调用回调:

方式一:DeviceEventEmitter(最常用的全局事件)

适用于:

  • 原生向 JS 广播事件

  • 如:监听硬件状态、传感器数据、UI 操作回调等

方式二:emitComponentEvent(组件事件机制)

适用于:

  • 原生组件向 JS 同步 UI 事件

  • 如:自定义组件的点击事件、加载事件、滑动事件等

方式三:callRNFunction(原生主动调用某个 JS 函数)

适用于:

  • 原生内容加载完成时通知 JS

  • 原生需要调用 JS 中某个模块的方法

  • C++ 层需要调用 JS 逻辑

下面详细讲解。

四、方式一:DeviceEventEmitter ------ 原生主动发送全局事件到 JS

ArkTS → JS 发送事件

你提供的示例中,ArkTS 使用 RNInstance.emitDeviceEvent

TypeScript 复制代码
this.ctx.rnInstance.emitDeviceEvent("clickMarqueeEvent", { params: { age: 18 } })

含义:

  • 事件名:clickMarqueeEvent

  • 携带数据:{age:18}

JS 侧监听事件

TypeScript 复制代码
import { DeviceEventEmitter } from 'react-native';

DeviceEventEmitter.addListener('clickMarqueeEvent', e => {
  console.log('Receive native event:', e);
});

场景示例:

  • 原生组件点击事件回传到 JS

  • 原生文件下载进度通知 JS

  • 原生网络变化通知 JS

五、方式二:emitComponentEvent ------ 原生 UI 组件事件上报

当你封装自定义原生组件(ArkTS / C++)时,需要将 UI 交互传回 JS。

ArkTS 调用

TypeScript 复制代码
this.ctx.rnInstance.emitComponentEvent(tag, "onLoad", payload)

参数说明:

  • tag:组件节点 id(React Fiber 对应的原生视图)

  • eventName:事件名(如 onLoad、onClick)

  • payload:数据对象

JS 侧接收(组件 props 中)

TypeScript 复制代码
<MyNativeView onLoad={(e) => console.log(e.nativeEvent)} />

C++ 示例

cpp 复制代码
m_eventEmitter->dispatchEvent("load", [=](facebook::jsi::Runtime& runtime) {
  auto payload = facebook::jsi::Object(runtime);
  auto source = facebook::jsi::Object(runtime);
  source.setProperty(runtime, "width", width);
  source.setProperty(runtime, "height", height);
  source.setProperty(runtime, "uri", uri.c_str());
  return payload;
});

适用于:

  • 图片加载事件

  • 视频播放进度

  • 自定义 UI 控件内部逻辑更新

  • 任意"组件级"的事件回调

六、方式三:callRNFunction ------ 原生主动调用 JS 模块的方法

这个能力非常强大,它允许原生直接调用 JS 内的函数。

ArkTS 调用:

TypeScript 复制代码
this.ctx.rnInstance.callRNFunction("JSTimers", "callTimers", [arg1, arg2]);

C++ 调用:

cpp 复制代码
instance->callJSFunction("JSTimers", "callTimers", std::move(getObject(id)));

场景非常广:

  • 原生某项任务完成 → 让 JS 执行逻辑

  • JS 中的某个模块需要由原生触发

  • C++ 层编写动画引擎、解码器,过程中主动调 JS

  • 原生通知 JS 更新状态、刷新 UI

七、实战:实现一个 OpenHarmony 原生组件向 RN JS 发送点击事件

下面我们整合内容,给一个完整示例流程。

ArkTS 侧自定义组件中:

TypeScript 复制代码
// 点击时通知 JS
onClick() {
  this.ctx.rnInstance.emitDeviceEvent("onMarqueeClick", {
    msg: "Marquee clicked",
    timestamp: Date.now()
  });
}

JS 侧监听:

TypeScript 复制代码
useEffect(() => {
  const listener = DeviceEventEmitter.addListener(
    "onMarqueeClick",
    (e) => {
      console.log("来自原生的点击事件:", e);
    }
  );

  return () => listener.remove();
}, []);

即可实现:

  • ArkTS → JS 实时事件推送
  • 支持自定义数据
  • 生命周期安全、性能可靠

总结

OpenHarmony 上的 RN 原生通信能力非常完善,通过 TurboModules、DeviceEventEmitter、emitComponentEvent、callRNFunction,这些能力已经足够支撑:

  • 全部系统能力调用(网络、传感器、相机、存储等)

  • UI 原生组件封装(ArkUI → JS)

  • 原生主动推送事件

  • C++ 调用 JS,实现高性能模块(解码器、播放器)

在 HarmonyOS / OpenHarmony 的生态中,RN 依然可以保持高性能与灵活性,让 JS 与原生之间协作顺畅。

相关推荐
后端小张42 分钟前
【鸿蒙2025领航者闯关】鸿蒙生态共建:智慧医疗领域的分布式革新与实践
分布式·华为·harmonyos·鸿蒙·鸿蒙系统·鸿蒙2025领航者闯关·开发者年度总结
lew-yu42 分钟前
博客摘录「 当前开源旗舰LLM主流架构介绍」2025年12月3日
笔记
冬夜戏雪43 分钟前
【java学习日记】【2025.12.3】【3/60】
学习
('-')43 分钟前
《从根上理解MySQL是怎样运行的》第二十四章笔记
数据库·笔记·mysql
LO嘉嘉VE1 小时前
学习笔记二十四:支持向量机-对偶问题
笔记·学习·支持向量机
爱凤的小光1 小时前
Git自我学习笔记
笔记·git·学习
玖日大大1 小时前
基于 Hugging Face Transformers 搭建情感分析模型:从原理到实战
人工智能·学习
森林小狗2 小时前
0基础快速入门SEO笔记
笔记
其美杰布-富贵-李2 小时前
SpaceClaim 流体域建模学习笔记
笔记·学习