第 43 期 - Taro 框架中 React 代码在 ArkUI 运行的原理
logoFRONTALK AI/12月5日 16:30/阅读原文

摘要

本文讲述 Taro 框架为使 React 代码在 ArkUI 运行,先实现自定义 Renderer 对接 React 转换为 Taro 虚拟节点树,再经三步转换映射到 ArkUI 结构,包括 Taro Element、Taro RenderNode 和 ArkUI Node 相关操作。

背景

鸿蒙系统发展迅速,开发者希望将跨平台应用迁移到鸿蒙平台。Taro 是流行的跨平台开发框架,鸿蒙采用 ArkUI 框架与 Taro 原本支持的平台差异大,将 Taro 的 React 开发模式与 ArkUI 对接是技术难题,本文将探讨 Taro 框架如何让 React 代码在 ArkUI 运行。

Taro 运行时原理介绍

从 React 到 Taro

React 跨平台的秘诀

Taro 运行时先执行 React 业务代码,React 的 Renderer 将虚拟节点操作映射到相应平台。Taro 团队设计了 Taro Renderer 充当 React 与 Taro 虚拟节点树的桥梁,将 React 操作转换为 Taro 的中间表示。

// 实现 Taro 的 Renderer 需要实现 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)
    },
    //...
}

通过实现 hostConfig 接口的方法,如createInstancecommitUpdate等,Taro Renderer 能将 React 操作转换为 Taro 虚拟节点树的操作,该虚拟节点树是 Taro 跨平台的核心。

从 Taro 到 ArkUI

Taro Element 转换 ArkUI 过程

在将 Taro 虚拟节点树转换为 ArkUI 时,要先在 ArkUI 层面实现与 Taro 组件对应的组件库,建立映射关系。但 Taro 虚拟节点树与 ArkUI 视图结构存在差异,如复合组件结构、层级位置调整、平台特定组件等,所以在生成渲染树时需要更复杂的转换过程,要维护一棵 Render Tree 做中间桥梁。

1. 根据组件类型 创建 Taro Element

根据组件类型实例化相应的 Taro 元素是将 React 组件转换为 Taro 内部表示的关键。

// 根据组件类型创建对应的 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 Element 后,要将其转换为 Taro RenderNode,进一步转化为更接近 ArkUI 结构的渲染节点。

// 创建 Taro RenderNode
void TaroSwiper::Build() {
    if (!is_init_) {
        // create render node
        TaroElementRef 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

最后将 Taro RenderNode 转换为实际的 ArkUI 节点,涉及与 ArkUI 底层 API 交互。

// 创建 ArkUI Node
void TaroSwiperNode::Build() {
    NativeNodeApi *nativeNodeApi = NativeNodeApi::getInstance();
    // 创建一个 Swiper 的 ArkUI 节点
    SetArkUINodeHandle(nativeNodeApi->createNode(ARKUI_NODE_SWIPER));
}

通过这三步在 C ++层面实现了 React 组件结构到 ArkUI 原生组件结构的映射。

总结

本文探讨 Taro 框架使 React 代码在 ArkUI 运行的过程,主要分两部分。一是 Taro 对接 React,通过自定义 Renderer 将 React 操作转换为 Taro 虚拟节点树操作;二是 Taro 对接 ArkUI,通过自定义 Renderer 转换为虚拟节点树后经三步转换映射到 ArkUI 结构,包括创建 Taro Element、Taro RenderNode 和 ArkUI Node,最终实现 Taro 应用在鸿蒙系统上准确渲染和运行并为跨平台开发提供支持。

 

扩展阅读

Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有