React Native跨平台鸿蒙开发高级应用原理:React Native 的组件渲染系统Fabric原理介绍
React Native正在向新架构Fabric迁移,计划2024年底正式启用。新架构通过简化渲染流程和优化C-API性能(如直接数据使用、属性Diff等)提升效率。鸿蒙团队提供了react-native-harmony适配包支持OpenHarmony平台。代码示例展示了新旧架构的类型定义差异:旧架构使用requireNativeComponent需要额外类型声明,而新架构的codegenNati
众所周知 React Native 自 2021 年开始就宣布支持新的渲染器 Fabric 并开始逐渐迁移新架构 ,据 RN 开发团队的计划逐步迁移并在 2024 年底将会将新架构上线到 RN 正式版默认启用,并逐步放弃对旧架构的支持(当然段时间不会立即将旧架构部分移除,会在一定时间内保持兼容,就如同燃油车到电车的过程,那自然现在的阶段就会出现油电混动车)所以作为依赖库的维护者,我们现在开发和迁移自己的依赖就是最好的时机。
RN库代码
- 在现行的 React Native 中,有很多属性是在 React 侧完成的封装,也有很多属性是平台独有的。为了达成这个效果,React Native 在 JS 侧根据
Platform增加了很多判断。所以,React Native 的鸿蒙化适配也需要增加OpenHarmony相关的平台判断,与相应的组件属性的封装。为此,鸿蒙化团队提供了react-native-harmony的 tgz 包,并通过更改metro.config.js配置,将该 tgz 包应用到 Metro Bundler 中。 - React Native 还提供了很多库的封装,例如 Codegen、打包工具等。为此,鸿蒙化团队提供了
react-native-harmony-cli的包,对这些库进行了OpenHarmony平台的适配,用于向开发者提供相关的功能。
Fabric
Fabric 是 React Native 的组件渲染系统。接收 React Native 传过来的组件信息,处理后发送给 OS,由 OS 完成页面的渲染。

在适配方案中,组件不通过复杂的流程对接到 ArkUI 的声明式范式上,而是直接使用ContentSlot对接到 ArkUI 的后端接口进行渲染,缩短了流程,提高了组件渲染的效率。C-API 的性能收益包括以下的几个部分:
- C 端最小化、无跨语言的组件创建和属性设置;
- 无跨语言前的数据格式转换,不需要将
string,enum等数据类型转换为object,可以在 CPP 侧直接使用对应的数据进行处理; - 可以进行属性 Diff,避免重复设置,降低了属性设置的开销。
React Fabric是基于Fabric.js的React组件库,主要用于创建可交互的画布应用,支持图形绘制、手势操作和插件扩展等功能。
核心功能
- 画布操作:支持矩形、文本等基础图形绘制,提供缩放、拖拽等交互功能 。
- 插件系统:内置Pinch(触摸缩放)、FreeDraw(自由绘制)等插件,需额外安装依赖(如hammerjs) 。
- 热区组件:可基于Fabric实现图片热区,支持链接绑定、样式切换和区域调整 。
安装与使用
安装命令:
npm install @cs-open/react-fabric
# 或
yarn add @cs-open/react-fabric
示例代码:
import { Canvas, Rect, Text } from '@cs-open/react-fabric';
function App() {
return (
<Canvas width={800} height={600}>
<Rect left={100} top={100} width={200} height={100} fill="red" />
<Text left={150} top={150} text="Hello Fabric!" fontSize={20} fill="white" />
</Canvas>
);
}
插件启用:
import { Pinch, FreeDraw } from '@cs-open/react-fabric/plugins';
<Canvas width={800} height={600}>
<Pinch />
<FreeDraw />
</Canvas>
通过下列代码可以对比出来新旧架构层在 Typescript(目前 Codegen 暂时仅支持 Flow 或 TypeScript 定义用于定义接口)的定义上区别
// 旧架构
import React from 'react';
import { requireNativeComponent, ViewStyle } from 'react-native';
const FeedAdComponent = requireNativeComponent('FeedAd');
export interface FeedAdProps {
codeid: string;
style?: ViewStyle;
onAdError?: Function;
}
const TxFeedAd = (props: FeedAdProps) => {
return (
<FeedAdComponent
codeid={props.codeid}
style={props.style}
onAdError={props.onAdError}
/>
)
}
// 新架构
import type { ViewProps } from 'react-native';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type {
DirectEventHandler,
Int32,
} from 'react-native/Libraries/Types/CodegenTypes'; // https://github.com/reactwg/react-native-new-architecture/discussions/27
export type AdFailWithErrorEventReply = Readonly<{
code: Int32;
message: string;
}>;
interface FeedViewProps extends ViewProps {
codeId: string;
onAdError?: DirectEventHandler<
Readonly<AdFailWithErrorEventReply>
>;
}
export default codegenNativeComponent<FeedViewProps>('FeedView');
通过上面 react-native-ad 中 Feed 广告的重构部分代码摘录就能看出来,首先旧架构中 requireNativeComponent 获取到的原生对象其实是一个 any 类型的 Comment 所以在导出组件时,通常需要另外定义一个用于导出合理类型声明的函数组件套用。而新架构上的话 codegenNativeComponent 直接通过定义类型泛型能够直接导出指定 props 类型的 Comment 组件。
更多推荐


所有评论(0)