基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章将深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕
背景
随着鸿蒙操作系统的快速发展,开发者们期待将现有跨平台应用迁移到鸿蒙平台。Taro作为一个流行的跨平台开发框架,其支持鸿蒙系统的可能性引起了广泛关注。
然而,鸿蒙系统采用全新的ArkUI框架作为原生UI开发方案,与Taro原本支持的平台存在显著差异。将Taro的React开发模式与ArkUI的声明式UI开发范式进行有效对接成为了一个技术难题。
本文将探讨Taro框架如何通过创新方案实现React代码在ArkUI上的运行。我们将解析Taro的运行时原理,剖析其如何将React组件转换为ArkUI可识别的结构,以及相关技术挑战和解决方案。
Taro运行时原理介绍
1. 从 React 到 Taro
React 跨平台的秘诀
在 Taro 的运行时中,首先执行的是开发者编写的 React 业务代码。这些代码定义了业务应用的结构、逻辑和状态管理。那么既然要对接React,那肯定先得了解它的核心架构,React是怎么运作的:
了解了React的基本架构后,我们可以清晰地看到,Renderer 作为渲染器,负责将React的虚拟节点操作最终映射到相应的平台上。例如,react-dom将这些操作对接到浏览器上,而react-native则将其对接到iOS或Android平台。这种设计使得React能够适配不同的运行环境。
正是基于这种思路,Taro 团队设计了 Taro Renderer。这个渲染器充当了 React 与 Taro 虚拟节点树之间的桥梁,使得 React 的操作可以被转换为 Taro 的中间表示。
通过实现 Taro Renderer 生成 Taro 虚拟节点树
ReactReconciler所需的 hostConfig 接口。这个接口定义了一系列方法,用于创建、更新和管理渲染目标平台的元素。以下是一些关键的 hostConfig 方法:
// 部分HostConfig接口实现的代码const hostConfig: HostConfig {// 创建Taro虚拟节点createInstance (type, props: Props, _rootContainerInstance, _hostContext, internalInstanceHandle: Fiber) {const element: TaroElement = TaroNativeModule.createTaroNode(type)precacheFiberNode(internalInstanceHandle, element)updateFiberProps(element, props)return element},// 更新属性commitUpdate (dom, updatePayload, _, oldProps, newProps) {updatePropsByPayload(dom, oldProps, updatePayload)updateFiberProps(dom, newProps)},// 插入节点insertBefore (parent: TaroElement, child: TaroElement, refChild: TaroElement) {parent.insertBefore(child, refChild)},// 移除节点removeChild (parent: TaroElement, child TaroElement) {parent.removeChild(child)},// ...}
2. 从 Taro 到 ArkUI
首先,我们需要在 ArkUI 层面实现一套与 Taro 组件对应的组件库。这个步骤至关重要,因为它建立了 Taro 组件和 ArkUI 组件之间的映射关系。例如,我们需要为 Taro 的 View、Text、Image 等基础组件创建对应的 ArkUI 组件。这样,当我们遍历 Taro 虚拟节点树时,就能找到每个节点在 ArkUI 中的对应实现。
在节点映射的过程中,我们注意到 Taro 虚拟节点树与实际 ArkUI 视图结构存在差异。这些差异主要体现在以下几个方面:
1. 根据组件类型 创建 Taro Element
// 根据组件类型创建对应的Taro节点std::shared_ptr<TaroElement> TaroDocument::CreateElement(napi_value &node) {// 获取组件类型TAG_NAME tag_name_ = TaroDOM::TaroElement::GetTagName(node);// 根据组件类型,创建对应的实例std::shared_ptr<TaroDOM::TaroElement> item;switch (tag_name_) {case TAG_NAME::SCROLL_VIEW: {item = std::make_shared<TaroDOM::TaroScrollView>(node);break;}case TAG_NAME::IMAGE:item = std::make_shared<TaroDOM::TaroImage>(node);break;}case TAG_NAME::SPAN:case TAG_NAME::TEXT: {item = std::make_shared<TaroDOM::TaroText>(node);break;}case TAG_NAME::SWIPER: {item = std::make_shared<TaroDOM::TaroSwiper>(node);break;}// ...}return item;}
2. Taro Element 创建 Taro RenderNode
// 创建 Taro RenderNodevoid TaroSwiper::Build() {if (!is_init_) {// create render nodeTaroElementRef element = std::static_pointer_cast<TaroElement>(shared_from_this());auto render_swiper = std::make_shared<TaroSwiperNode>(element);render_swiper->Build();}}
3. Taro RenderNode 创建 ArkUI Node
// 创建 ArkUI Nodevoid TaroSwiperNode::Build() {NativeNodeApi *nativeNodeApi = NativeNodeApi::getInstance();// 创建一个Swiper的ArkUI节点SetArkUINodeHandle(nativeNodeApi->createNode(ARKUI_NODE_SWIPER));}
总结
1. Taro对接React
2. Taro对接ArkUI
1.创建Taro Element:这一步将React组件转换为Taro内部表示。
2.创建Taro RenderNode:将Taro的内部表示进一步转化为更接近ArkUI层级结构的渲染节点。
3.创建ArkUI Node:最后一步是将Taro RenderNode转换为实际的ArkUI节点,直接与ArkUI的底层API交互。
系列往期精选:
扫一扫,加入技术交流群


