React Native跨平台鸿蒙开发实战:JS 与 ArkTS Native的通信机制详解

人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1 万小时的锤炼是任何人从平凡变成超凡的必要条件。------------ 马尔科姆·格拉德威尔

🌟 Hello,我是 Xxtaoaooo!

🌈 "代码是逻辑的诗篇,架构是思想的交响"

React Native 跨平台鸿蒙开发实战:JS 与 ArkTS/Native 的通信机制详解

在 React Native (RN) 开发中,JavaScript 运行在独立的线程中,而设备的原生能力(如相机、传感器、分布式软总线)则位于原生层。如何高效、安全地打通这两者,是跨平台开发的核心。在鸿蒙系统(HarmonyOS)中,我们通过 TurboModules 和 NativeModules 机制,实现 JS 与 ArkTS 的无缝双向通信。


一、鸿蒙原生能力调用的架构基础

鸿蒙系统提供了强大的分布式能力和丰富的硬件 API,要让 RN 应用享受到这些红利,必须通过 Bridge(桥接)或 JSI(JavaScript Interface)技术。

1.1 通信架构概览

RN 在鸿蒙上的通信机制主要分为两类:

  1. 异步通信 (Native Modules):基于 Bridge,适用于非高频、耗时操作(如文件读写、网络请求)。
  2. 同步通信 (TurboModules / JSI):基于 C++ 绑定,适用于高频、低延迟场景(如动画驱动、传感器数据)。

下图展示了 JS 侧调用鸿蒙原生 Sensor 能力的时序交互。
HarmonyOS SDK ArkTS/Native Layer TurboModule Bridge JS Thread (RN) HarmonyOS SDK ArkTS/Native Layer TurboModule Bridge JS Thread (RN) 传感器数据订阅流程 loop [传感器数据回调] 1. subscribeSensor('accelerometer') 2. Invoke Native Method 3. sensor.on(SENSOR_TYPE_ID_ACCELEROMETER) 4. Data Changed Event 5. Send Event to JS 6. DeviceEventEmitter.emit()

图 1:JS 与 ArkTS 传感器数据交互时序图


二、实现 JS 调用 ArkTS 模块

让我们通过一个具体案例------调用鸿蒙系统的弹窗(Toast)能力,来演示如何编写一个自定义的 Native Module。

2.1 ArkTS 侧实现

首先,在鸿蒙工程的 entry/src/main/ets 目录下创建一个 Native Module。我们需要继承 RNModule 并实现相关接口。

typescript 复制代码
// HarmonyToastModule.ts
import { RNModule, TurboModuleContext } from '@rnoh/react-native-openharmony/ts'
import promptAction from '@ohos.promptAction'

export class HarmonyToastModule extends RNModule {
  constructor(ctx: TurboModuleContext) {
    super(ctx)
  }

  // 定义模块名称,JS 端将通过此名称调用
  getName() {
    return 'HarmonyToast'
  }

  // 暴露给 JS 的方法
  show(message: string, duration: number) {
    promptAction.showToast({
      message: message,
      duration: duration,
    })
  }
}

核心点评

ArkTS 代码直接调用了 @ohos.promptAction,这是鸿蒙原生提供的轻量级提示接口。通过继承 RNModule,我们将这个能力包装成了 RN 可识别的模块。

2.2 JS 侧封装

在 React Native 项目中,我们需要创建一个对应的 TS 接口文件,以便在业务代码中获得类型提示。

typescript 复制代码
// HarmonyToast.ts
import { TurboModule, TurboModuleRegistry } from 'react-native'

export interface Spec extends TurboModule {
  show(message: string, duration: number): void
}

// 获取 Native 模块,如果获取不到则返回 null
export default TurboModuleRegistry.get<Spec>('HarmonyToast')

三、实现 ArkTS 主动发送事件到 JS

除了 JS 主动调用,原生层也经常需要主动向 JS 发送消息,例如系统电量变化、分布式设备连接状态变更等。

3.1 ArkTS 发送事件

使用 RNInstance 提供的 emitDeviceEvent 方法。

typescript 复制代码
// 在某个 ArkTS 服务或组件中
this.ctx.rnInstance.emitDeviceEvent('onDeviceConnected', {
  deviceId: 'device_123',
  deviceType: 'tablet',
})

3.2 JS 监听事件

在 RN 组件中,使用 DeviceEventEmitter 进行监听。

javascript 复制代码
import { DeviceEventEmitter, useEffect } from 'react-native'

function DeviceMonitor() {
  useEffect(() => {
    const subscription = DeviceEventEmitter.addListener(
      'onDeviceConnected',
      (event) => {
        console.log('新设备连接:', event.deviceId)
      }
    )

    return () => {
      subscription.remove() // 记得清理监听
    }
  }, [])

  return null
}

四、安全性与权限处理建议

在调用原生能力时,权限管理是不可忽视的一环。

  1. 最小权限原则 :仅申请业务必需的权限(如 ohos.permission.CAMERA)。
  2. 动态申请:对于敏感权限,必须在运行时向用户请求授权。

4.1 权限申请流程

已授权
未授权


JS 发起调用
检查权限
执行原生逻辑
调用 requestPermissionsFromUser
用户同意?
返回权限拒绝错误

图 2:鸿蒙应用运行时权限申请流程

在 ArkTS 中,使用 abilityAccessCtrl 来管理权限:

typescript 复制代码
import abilityAccessCtrl from '@ohos.abilityAccessCtrl'

// 检查并申请权限
async function requestCameraPermission(context: any) {
  const atManager = abilityAccessCtrl.createAtManager()
  const result = await atManager.requestPermissionsFromUser(context, [
    'ohos.permission.CAMERA',
  ])
  return result.authResults[0] === 0
}

🌟 嗨,我是 Xxtaoaooo!

⚙️ 【点赞】让更多同行看见深度干货

🚀 【关注】持续获取行业前沿技术与经验

🧩 【评论】分享你的实战经验或技术困惑

作为一名技术实践者,我始终相信:

每一次技术探讨都是认知升级的契机,期待在评论区与你碰撞灵感火花 🔥

欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

相关推荐
Daniel李华12 小时前
echarts使用案例
android·javascript·echarts
北原_春希12 小时前
如何在Vue3项目中引入并使用Echarts图表
前端·javascript·echarts
JY-HPS12 小时前
echarts天气折线图
javascript·vue.js·echarts
尽意啊12 小时前
echarts树图动态添加子节点
前端·javascript·echarts
吃面必吃蒜12 小时前
echarts 极坐标柱状图 如何定义柱子颜色
前端·javascript·echarts
O_oStayPositive12 小时前
Vue3使用ECharts
前端·javascript·echarts
竹秋…12 小时前
echarts自定义tooltip中的内容
前端·javascript·echarts
宝贝露.12 小时前
Axure引入Echarts图无法正常显示问题
前端·javascript·echarts
人良爱编程12 小时前
Hugo的Stack主题配置记录03-背景虚化-导航栏-Apache ECharts创建地图
前端·javascript·apache·echarts·css3·html5
来颗仙人掌吃吃12 小时前
解决Echarts设置宽度为100%发现宽度变为100px的问题(Echarts图标宽度自适应问题)
前端·javascript·echarts