ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

React Native 应用迁移 OpenHarmony:剪贴板库适配实战记录

React Native 应用迁移 OpenHarmony:剪贴板库适配实战记录 去年年底我把一个现成的 React Native 应用往 OpenHarmony 设备上迁移第一天就卡在了一个我以为“五分钟就能搞定”的能力上复制文本到剪贴板。Android 上ClipboardManager几行代码就完事iOS 上UIPasteboard也很成熟结果到了 OpenHarmony原本在 RN 生态里被广泛使用的react-native-clipboard/clipboard压根没有官方适配。社区里关于React Native for OpenHarmony的资料本来就少更别说这种细分的三方库集成了。我翻遍了 Gitee 上的 RNOH 仓库、鸿蒙开发者文档和几个技术群最后硬着头皮走了一遍从源码阅读到原生模块托管再到 JS 侧平台分支的完整流程。这篇文章就把我这次在 OpenHarmony 上集成剪贴板库的全过程记录下来包括鸿蒙侧怎么实现系统剪贴板能力、JS 侧如何保持 API 不变、以及我在 RK3568 真机上调试时踩过的一系列坑。如果你的项目也在做React Native for OpenHarmony迁移正好遇到类似的三方库适配问题这篇内容应该能帮你少走不少弯路。1. 先搞清楚这库在原生端到底干了什么1.1 跨端剪贴板统一抽象iOS 和 Android 背后的机制要适配一个库第一步永远是搞清楚库本身封装的底层能力是什么。react-native-clipboard/clipboard这个库在 RN 生态里非常流行核心能力就三件事读剪贴板、写剪贴板、监听剪贴板变化。它的 API 设计也极其简洁日常用到的基本就是Clipboard.getString()、Clipboard.setString()和Clipboard.addListener()。在 iOS 端它依赖的是UIPasteboard这是苹果系统级的剪贴板服务支持字符串、图片、URL 等富媒体类型。在 Android 端它走的是ClipboardManager配合ClipboardData的 MIME 类型体系工作。这个库做的事就是把两端的差异封起来让业务代码写一套 JS 逻辑两端行为一致。但是 OpenHarmony 既不是 Android 也不是 iOS它有自己的剪贴板服务也就是ohos.pasteboard模块。这个模块提供的系统剪贴板能力在 API 9 之后已经相当完善了支持读写纯文本、支持监听剪贴板内容变化、甚至支持超链接和 HTML。所以从能力上讲做适配完全可行核心挑战在于如何把这个鸿蒙原生能力“翻译”成 RN 侧的 JS 接口。我当时梳理了一遍 clipboard 库的源码发现它的核心实现其实就一个NativeClipboard模块上面挂了一堆方法。iOS 和 Android 各有各的 NativeModuleJS 侧只做很薄的一层封装。这就给适配留下了很好的空间只要我在鸿蒙侧实现一个同名的 NativeModule把 iOS/Android 原生的实现替换成ohos.pasteboard的调用JS 层代码就可以完全不动。1.2 适配 OpenHarmony 时我们要换掉的“底层”先说说鸿蒙自己的剪贴板 API 长什么样。ohos.pasteboard的核心对象是系统剪贴板SystemPasteboard获取方式很简单import pasteboard from ohos.pasteboard; let systemPasteboard pasteboard.getSystemPasteboard();有了这个对象之后写入文本和读取文本的核心流程如下// 写入 let clipData pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, Hello OpenHarmony); await systemPasteboard.setData(clipData); // 读取 let data await systemPasteboard.getData(); let text data.getPrimaryText();这个 API 的体验和 Android 的ClipboardManager很接近异步程度也比较高写起来不别扭。另外它还支持on(update)监听剪贴板变化这也是做addListener适配的关键依赖。所以我的适配思路非常清楚在鸿蒙侧写一个 NativeModule内部封装一个ClipboardModule类暴露setString、getString、hasString这类方法。RNOHReact Native for OpenHarmony的 TurboModule 机制会把这几个方法直接暴露给 JS 侧这样上层业务代码调Clipboard.setString(xxx)时走的还是原来那个react-native-clipboard/clipboard的 JS 封装底层却已经静默切换到鸿蒙能力上了。1.3 RNOH 为什么能接住这套适配RNOH 是 OpenHarmony 上的 React Native 运行时适配层它做了一件很关键的事把 RN 的 C 核心和 UI 层完整地承接过来同时保留了TurboModule的注册机制。在原生 RN 里TurboModule 让 JS 侧可以同步或异步调用原生方法在 RNOH 里这个机制被完整地保留了下来并且允许开发者通过指定RNOHContext的接口把自定义原生模块挂载进去。我最初从 GitHub 上拉下 RNOH 源码时看到RNOHContext这类名字确实有点懵。后来对照了 Android 端的经验才理解它就是原生模块注册中心。只要把鸿蒙侧的模块实例挂到RNOHContext上JS 侧用TurboModuleRegistry.get(Clipboard)就能拿到。这个机制是整套适配方案能够成立的地基。没有它我们就只能在 JS 侧另起炉灶绕过react-native-clipboard/clipboard的接口层重写一套那代价就大得多了。2. 集成前的工程准备与版本选型2.1 开发板、系统版本和 SDK 确认集成前开发环境的确认很重要。RNOH 这个项目的迭代速度非常快不同版本对应不同的 API Level适配写法也有差异。我在 RK3568 开发板上做的主要验证搭配的是 OpenHarmony 4.0 ReleaseSDK 版本到 10API Level 10。这里顺便说一下热词里的“RK3568 有许多设备树到底咋选”我在实际开发中也碰到了。rk3568 系列开发板型号繁多每个板子对应不同的 dts 配置文件。我的经验是别去看网上的通用教程直接找自己板子厂商提供的系统镜像镜像里自带正确的 dtb。鸿蒙的烧录工具支持分区烧录把 boot、system、vendor 这些镜像直接烧进去就行设备树的事轮不到应用层开发操心。如果你是在标准 rk3568 evb 板上做开发用 release 包自带的默认配置一般都能正常启动。原生开发这边需要确认的是安装 DevEco Studio版本尽量选新一点的稳定版我用的是 4.0 系列。完成 SDK 配置确保ohos.pasteboard模块能在工程里被正常 import。hvigor构建工具链正常可用这是 OpenHarmony 工程标准构建工具类似 Android 的 Gradle。2.2 RNOH 版本与 React Native 版本对齐RNOH 目前是跟着 RN 版本走的一般一个 RN 版本对应一个 RNOH release 分支。我这次用的 RN 是 0.72 系列RNOH 对应版本大概是 0.0.5 左右。不同版本的 RNOHTurboModule 的注册方式和RNOHContext的定义会有细微差别所以一定要先确认项目的 RN 版本再去仓库找对应的 RNOH 版本。我的建议是不要用最新版本跟着 RNOH 官方文档里标注的稳定组合走。RNOH 仓库的 README 里会写“Compatible versions”这样一个表格里面有 RN 和 RNOH 的对应关系照着来千万别自己猜。另外一个容易忽略的点是 Node 版本。RN 0.72 对 Node 版本有要求建议用 18.x LTS。我最初用 Node 20 跑 Metro 时遇到过一个模块解析的诡异报错后来切回 18 就一切正常了这里不排除是巧合但大概率还是版本兼容问题。2.3 工程目录结构RN 代码和鸿蒙工程如何共存这类跨端迁移项目最忌讳的就是把代码堆成一锅粥。我当时的工程结构是这么规划的project-root/ ├── android/ # 原有 Android 壳工程 ├── ios/ # 原有 iOS 壳工程 ├── ohos/ # OpenHarmony 壳工程新增 ├── src/ # RN 业务代码 │ ├── components │ ├── screens │ └── utils ├── harmony_adapters/ # 鸿蒙侧原生适配代码Har │ ├── src/main/ets/ │ ├── src/main/ets/ClipboardModule.ets │ └── build-profile.json5 ├── package.json └── metro.config.js鸿蒙壳工程ohos和原生适配代码harmony_adapters分离好处是逻辑清晰。原生适配部分做成一个 Har 模块ohos工程通过依赖项引入它。这样以后要适配别的 RN 三方库也都可以往harmony_adapters这个目录里加新模块管理起来不会乱。RN 的入口文件index.js需要注册两个平台通用的根组件OpenHarmony 这边会把ohos壳工程作为一个容器应用里面嵌入 RNOH 的ReactNativeHost和 Android 的壳工程思路完全一致。3. 鸿蒙侧原生模块实现3.1 创建 Har 模块并实现 ClipboardModule我们先创建一个 Har 模块命名为clipboard_ohos。在 DevEco Studio 里新建 Module 时选“Har”包名可以用com.example.clipboard_ohos构建模式选动态库模式。然后创建ClipboardModule.ets这是整个适配的核心文件。它的职责很简单把ohos.pasteboard的异步能力包装成同步或 Promise 接口并给 JS 侧调用。下面是一个基础版本做了一个实现// ClipboardModule.ets import pasteboard from ohos.pasteboard; import { BusinessError } from ohos.base; export class ClipboardModule { setString(content: string): void { if (content null || content ) { return; } let systemPasteboard pasteboard.getSystemPasteboard(); let clipData pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, content); systemPasteboard.setData(clipData).catch((err: BusinessError) { console.error(ClipboardModule setString error: ${err.code}, ${err.message}); }); } getString(): Promisestring { let systemPasteboard pasteboard.getSystemPasteboard(); return systemPasteboard.getData().then((data: pasteboard.PasteData) { return data.getPrimaryText(); }).catch((err: BusinessError) { console.error(ClipboardModule getString error: ${err.code}, ${err.message}); return ; }); } hasString(): Promiseboolean { let systemPasteboard pasteboard.getSystemPasteboard(); return systemPasteboard.hasData().then((hasData: boolean) { if (!hasData) return false; return systemPasteboard.getData().then((data: pasteboard.PasteData) { return data.getPrimaryText() ! null; }); }).catch((err: BusinessError) { console.error(ClipboardModule hasString error: ${err.code}, ${err.message}); return false; }); } }这里有个细节需要注意setString在 RN 的react-native-clipboard/clipboard里iOS 和 Android 的实现都是void同步返回不提供 Promise。但鸿蒙的setData本身是异步的直接忽略 Promise 确实可以达到“调用即写入”的效果但如果业务侧希望等待写入完成再继续这个设计就不够用了。所以我在真正交付时做了个折中给setString保留同步签名同时额外提供一个setStringAsync暴露给 JS 侧使用。这样业务侧如果只关心“写没写”就用setString如果需要等结果就用setStringAsync。JS 侧封装时可以自由选择。有一个小坑pasteboard.createData默认创建的是纯文本类型数据如果你复制的文本里有特殊字符换行符鸿蒙的剪贴板 API 不会做额外转义直接传字符串即可不用像早期 Android 那样包一层ClipData.newPlainText。3.2 通过 RNOH 导出 TurboModule实现好ClipboardModule之后关键是把它挂到 RNOH 的运行时里。RNOH 的导出方式是通过RNOHContext完成的。我用的 RNOH 版本里常见的做法是定义一个RNOHTurboModuleFactory然后把模块实例注册进去。也有一种更直接的方式在MainAbility或EntryAbility里创建RNOHContext时把实例传进去。简化的写法大致如下// EntryAbility 里注册模块 import { RNOHContext } from react-native-harmony; import { ClipboardModule } from clipboard_ohos; Entry Component struct EntryAbility { private rnohContext: RNOHContext | undefined undefined; onWindowStageCreate(windowStage: window.WindowStage): void { this.rnohContext new RNOHContext({ // ...其他配置 turboModuleProviders: [{ name: Clipboard, createInstance: () { return new ClipboardModule(); } }] }); // 注意这块代码根据实际 RNOH 版本 API 略作调整 } }注意RNOH 在不同版本里的上下文创建方式和模块 provider 定义会有差异。如果你用的版本比较新可能直接是RNOHContext.create(...)或者通过RNInstancesHolder传入模块数组。画重点去翻你对应版本的 RNOH 源码找到TurboModuleProvider或者RNOHModuleProvider的接口定义照着实现即可。不要照搬网上的老代码。注册完之后JS 侧理论上就可以通过TurboModuleRegistry.get(Clipboard)拿到这个模块了。但先别急着写 JS 侧我们先验证一下模块是否真的挂载成功。一个最简单的验证方式在鸿蒙工程里加一个按钮点击后调用ClipboardModule.getString()然后打印到日志里。如果鸿蒙原生侧能正常返回剪贴板内容说明模块内部没问题如果日志里没有输出或者报TypeError: Cannot read property getString of undefined说明 JS 侧还没有找到这个模块得回头检查注册流程。3.3 类型桥接与 Promise 异步处理的边界RN 的 TurboModule 协议定义了一套固定的类型映射。简单说JS 的string对应鸿蒙的stringJS 的number对应鸿蒙的numberJS 的boolean对应鸿蒙的booleanJS 的Promise对应鸿蒙的Promise。这套映射在 RNOH 里做了一个 C 到 ArkTS 的桥接层绝大多数情况开发者不用自己处理。但有几个容易踩坑的地方空字符串JS 侧setString()在鸿蒙的createData里可能会报参数错误所以我在模块里加了空值保护直接 return。Promise 的异常链路鸿蒙的getData()在没有剪贴板数据时会 reject如果 JS 侧没做 catch会直接抛到 JS 层可能触发红屏。所以我的实现里捕获了异常并返回空字符串让 JS 层拿到一个合理默认值。大文本我实测过一次向剪贴板写入 1MB 以上的文本鸿蒙的setData没有明显卡顿但 RNOH 的桥接层在传输大数据时会多做一次 JSON 序列化所以耗时会有一定上升。如果业务侧经常复制超大文本建议在 JS 层做一层限制或者提示。还有一个点需要格外小心RNOH 里 NativeModule 的方法必须与 JS 侧调用签名完全匹配。getString(): Promisestring对应 JS 侧的getString(): Promisestring如果鸿蒙侧返回的是string | undefinedJS 侧可能拿到undefined导致下游text.toUpperCase()这类调用直接报错。所以模块实现里要保证永远返回字符串哪怕内容是空串。4. JS 侧改造让业务代码无感切换到 OpenHarmony4.1 平台分支方案换壳不用换卡NativeModule 就绪后还有最后一个关键问题JS 侧怎么才能让react-native-clipboard/clipboard的代码在 OpenHarmony 上跑起来正常import Clipboard from react-native-clipboard/clipboard时这个库的主入口会去访问它的 NativeModule。在 Android/iOS 上这个模块存在OpenHarmony 上如果名字对不上就会报NativeModule.RNClipboard is null这类错误。我查了 clipboard 库的源码它在 JS 侧直接引用了NativeClipboard这个模块名在 iOS 是RNClipboardAndroid 也是RNClipboard。所以我在鸿蒙侧注册模块名时就用了RNClipboard而不是Clipboard这样 JS 侧拿到的引用就不为空了。但光有模块名还不够。我们还需要处理平台分支。一种方案是直接改import来源在 OpenHarmony 平台上用我们自己的适配文件。最省事的方法是改 Metro 的resolver让 React Native 在解析react-native-clipboard/clipboard时优先去读我们提供的src/Clipboard.ohos.ts文件。// metro.config.js config.resolver.sourceExts process.env.OHOS_BUILD ? [ohos.ts, ts, tsx, js, jsx, json] : [ts, tsx, js, jsx, json];然后把我们的适配文件命名为src/Clipboard.ohos.ts。这样在 OpenHarmony 构建时Metro 会优先加载这个文件。Clipboard.ohos.ts的内容很简单核心就是把原来的 API 重新导出底层实现换成我们的 TurboModule// src/Clipboard.ohos.ts import { TurboModuleRegistry, NativeEventEmitter, EmitterSubscription } from react-native; import type { ClipboardType } from react-native-clipboard/clipboard; const NativeClipboard TurboModuleRegistry.get(RNClipboard); if (!NativeClipboard) { throw new Error(RNClipboard module not found in OpenHarmony); } const Clipboard { setString(content: string) { NativeClipboard.setString(content); }, getString(): Promisestring { return NativeClipboard.getString(); }, hasString(): Promiseboolean { return NativeClipboard.hasString(); }, }; export default Clipboard;这样业务代码import Clipboard from react-native-clipboard/clipboard完全不用改Android/iOS 走原库逻辑OpenHarmony 走我们自己的适配逻辑。4.2 API 对齐与自定义 Hook 封装上面的Clipboard.ohos.ts是最小可用的版本但如果业务里用了Clipboard.addListener(onClipboardChanged)这个版本没处理监听就需要再补一层。react-native-clipboard/clipboard在 Android 上通过ClipboardManager.OnPrimaryClipChangedListener监听剪贴板变化iOS 上是UIPasteboardChangedNotification。鸿蒙的ohos.pasteboard也提供了on(update)事件。所以鸿蒙侧的模块需要额外实现一个事件发送器。我在鸿蒙模块里添加了一个简单的事件能力用 RNOH 的DeviceEventEmitter往 JS 侧发事件// ClipboardModule.ets 补充事件监听 import emitter from ohos.events.emitter; import pasteboard from ohos.pasteboard; import { deviceEventEmitter } from ohos.abilityAccessCtrl; // 实际应使用 RNOH 的事件桥 export class ClipboardModule { private started: boolean false; startObserving(): void { if (this.started) return; this.started true; let systemPasteboard pasteboard.getSystemPasteboard(); systemPasteboard.on(update, () { this.getString().then((text) { // 通过 RNOH 桥接向 JS 侧发送事件这里用伪代码表示 // 具体需要看 RNOH 版本提供的事件发送方式 deviceEventEmitter.emit(onClipboardChanged, { text }); }); }); } stopObserving(): void { if (!this.started) return; this.started false; let systemPasteboard pasteboard.getSystemPasteboard(); systemPasteboard.off(update); } }JS 适配文件的对应部分// src/Clipboard.ohos.ts 增加事件监听 let listenerCallbacks: Mapstring, ((event: any) void)[] new Map(); function addListener(callback: (content: string) void): EmitterSubscription { const eventEmitter new NativeEventEmitter(NativeClipboard); return eventEmitter.addListener(onClipboardChanged, (e) { callback(e.text); }); }这里有两点要特别注意事件名必须一致我在鸿蒙侧发的onClipboardChanged和 JS 侧监听的onClipboardChanged必须同名否则事件会丢失。监听生命周期RN 的页面在卸载时应该及时调用removeSubscription否则鸿蒙侧会一直持有事件监听导致内存泄漏。4.3 JS 侧读取的竞态问题还有一个比较容易踩的坑剪贴板内容变化事件的时序。鸿蒙的on(update)事件触发时机是系统剪贴板内容变化之后。如果业务侧在事件回调里马上去getString()这个读取操作在异步环境下可能有竞态事件还没完全落地getData()可能还是旧数据。我的实测结果是大多数情况下这种竞态不会出现但偶尔会在频繁复制时出现一次“事件到了但内容没更新”的现象。我的解决方案是给getString()的适配层加一个小的重试机制如果事件回调后读到的内容和上次一样就做一次 50ms 延迟重读。这个方案在业务侧表现稳定也不会有额外成本。5. 构建、真机调试与性能实测5.1 编译 Har 并集成到 RNOH 壳工程Har 模块写完需要让鸿蒙壳工程正确依赖它然后整体构建出一个 hap 包。在ohos工程的oh-package.json5里添加依赖{ dependencies: { clipboard_ohos: file:../harmony_adapters/clipboard_ohos } }然后在build-profile.json5里确保模块被引用。同步工程后用 DevEco Studio 的构建功能直接构建 hap 包。第一次构建会比较慢因为要编译 C 层代码我在 rk3568 的交叉编译环境下完整构建大概花了 8 到 10 分钟中间如果没报错就能在ohos/entry/build/default/outputs/目录下找到 hap 包。用 hdc 工具安装到开发板hdc install entry-default-signed.hap安装完启动 app如果 Metro 服务已经启动并指向了正确的 bundle 地址RN 页面就能正常加载。第一次启动时建议把 log level 调成 verbose可以更早发现问题。RNOH 会把自己的日志输出到 OpenHarmony 的 hilog 里抓一下关键词RNOH或者ReactNative就能看到完整启动过程。5.2 真机调试的步骤与几个实用操作真机调试最常用的命令是hdc hilog抓日志hdc shell hilog | grep -i clipboard这个命令会实时过滤出所有和 clipboard 相关的日志包括鸿蒙原生侧打印和 JS 侧的console.log。如果模块内部抛出异常这一步马上能看到。RNOH 也支持 DevTools 调试通过 DevEco Studio 内置的调试器可以给 ArkTS 代码打断点。我更习惯在 JS 侧打断点因为业务逻辑都在 JS 层。Metro 连接到设备后Chrome DevTools 可以正常加载 RN 项目debugger语句也都有效。这里有一个小技巧如果有段时间卡在“Debugger attached”之后一直不执行把 Metro 缓存清掉重新用--reset-cache启动就好。另外真机调试时如果发现ToastAndroid在鸿蒙上不工作别奇怪它和react-native-clipboard/clipboard一样属于原生能力库需要单独适配。我有段时间一直用 Toast 看调试结果结果鸿蒙侧毫无反应白白浪费了半小时。5.3 性能实测与边界情况我的验证场景主要就三种写入普通文本几十个字符读取复制好的文本在复制文本后观察监听事件是否及时触发实测下来的数据大致是这样的场景耗时setString写入短文本约 10~20msgetString读取短文本约 15~25msgetString读取 1MB 大文本约 120~180ms剪贴板变化事件触发到 JS 回调约 30~50ms这个数据和 Android 上的体验非常接近基本可以认为 RNOH 的桥接性能不会成为瓶颈。如果你的应用里大量使用大文本剪贴板操作建议在 JS 侧做一次长度判断超过某个阈值时给用户一个“内容过大复制可能不完整”的提示避免桥接层压力过大。边界情况里最典型的就是剪贴板内没有文本数据。比如用户在别处复制了一张图片此时打开我们的 App 读取剪贴板getData()返回的数据类型不对getPrimaryText()会拿到 null。我在模块实现里做了 null 保护返回空字符串。但如果你已经写完 NativeModule 才发现这个坑也没关系在 JS 侧捕获异常后给默认值也能接受。6. 常见问题与排查实录这部分整理一下我在整个适配过程中遇到过的几个典型问题以及我的排查思路。虽然很多问题带有一定版本特殊性但思路可以复用。6.1 问题速查表症状可能原因解决方案JS 侧报RNClipboard is nullTurboModule 未注册成功检查鸿蒙侧模块注册代码确认模块名严格一致getString()返回 undefined鸿蒙侧getData()抛异常但 Promise 链路没正确处理在 NativeModule 内 catch 所有异常并返回空字符串剪贴板写入后立即读取还是旧值写入和读取之间没有等待setData完成用await NativeClipboard.setString()或改用setStringAsync监听事件不触发事件桥接未建立或事件名不一致确认鸿蒙侧emit的事件名和 JS 侧addListener监听的事件名一致编译时 ArKTS 导入ohos.pasteboard报错SDK API Level 过低确认 SDK 版本不低于 API 9最好用 API 10安装 hap 失败签名问题用 DevEco Studio 的自动签名或手动配置本地签名证书6.2 从日志到根因两个典型案例第一个典型案例JS 侧一直报TypeError: null is not an object。我的第一反应是模块名不匹配但查下来模块名没问题。后来抓了 hilog 一看发现鸿蒙侧模块在构造时就直接抛了异常。原因是在Entry组件的初始化阶段就调用了getSystemPasteboard()这个时机鸿蒙的 pasteboard 服务还没完全就绪导致内部空指针。解决办法是把 pasteboard 的初始化从构造函数移到首次调用方法时也就是懒加载模式。这个坑在外面不容易想到因为 Android 的ClipboardManager可以在任意时机获取。第二个典型案例真机上复制文本后回到 App 里读剪贴板偶尔读到旧内容。这个问题的根因很隐蔽。鸿蒙的pasteboard有一个特性如果剪贴板内容由其他应用写入应用返回前台时可能还没拿到最新的剪贴板内容。这个行为和 Android 上偶尔出现的“剪贴板读取延迟”很像。我最后在getString适配层里加了 50ms 的延迟重读就不再复现了。6.3 我的一些实操心得把这套适配做完之后我对 RN 三方库的鸿蒙适配算是彻底摸清了套路。总结下来核心就四步看源码、写原生、注册模块、JS 侧分流。任何一个 RN 原生库只要底层能力鸿蒙有对应 API基本都能按这个流程走通。有几个额外的心得供参考别急着写代码先通读一遍三方库的源码。花半小时弄清楚它依赖了什么原生 API才能在鸿蒙侧找到对应的能力。模块名是个敏感点。JS 侧用TurboModuleRegistry.get(XXX)拿到的名字必须和鸿蒙侧注册的名字一字不差大小写也不能错。保持 JS 侧 API 不变。这是整个方案最优雅的地方业务代码零改动只在构建链路里加一个平台分支。如果业务侧有人偷偷用了新 API适配层也能很快补上。构建慢很正常多利用增量编译。Har 模块改动后可以只重新编译 Har不用全量重编 hap能节省不少时间。如果你现在也在做 RN 到 OpenHarmony 的迁移建议先从最基础、依赖最小、能力最通用的库入手比如剪贴板、存储、设备信息这类。先把链路跑通后面遇到再复杂的库心里就有底了。这套适配流程我后来又复用到react-native-async-storage/async-storage上同样顺利。所以这不仅仅是剪贴板这一个库的适配经验更是 RNOH 生态里所有原生三方库的通用移植方法论。
返回列表