npm 包 react-reconciler 使用教程

阅读时长 13 分钟读完

React 是一个非常流行的前端框架,它提供了一种声明式的编程方式来构建用户界面。但是,React 的工作原理并不容易理解,更不用说从底层实现一个类似 React 的框架了。

幸运的是,Facebook 开源了一个 npm 包叫做 react-reconciler,它提供了一些底层的构建块来实现自己的 React-likes 框架。在本篇文章中,我们将会了解 react-reconciler 的使用教程,深入探讨其原理,并提供一些示例代码。

什么是 React 协调器?

在了解 react-reconciler 之前,我们需要先了解 React 的协调器(也称为调和器)。React 协调器是 React 的核心算法,用于将应用程序状态映射到视图层级。在 React 库中,我们通常使用 ReactDOM 在 Web 上渲染界面。ReactDOM 实现了针对 Web 平台的协调器,它负责将 React 元素(Element)转换为 DOM 元素。

但是,React 还可以使用同样的编程模型来构建其他类型的 UI,例如移动应用程序、三维游戏、VR 和 AR 应用程序等。为了支持这些场景,React 团队提供了一个通用的协调器接口,即 react-reconciler。这个接口包含了一些基础算法和钩子,您可以实现自己的协调器,并在特定的平台上运行。

如何使用 react-reconciler?

我们来看一个基础的例子,如何使用 react-reconciler 构建一个简单的文本组件。

首先,我们需要安装 react-reconciler:

然后,我们创建自己的协调器。在这个例子中,我们称之为 MyRenderer:

接下来,我们定义我们的组件,这个例子只是一个简单的文本组件:

最后,在我们自定义的实现中,我们需要为 MyRenderer 添加一些方法,例如 createInstance、appendChild 等等。可以想象一下,这些方法称为 Reconciler Host Config,它们提供了外部环境和自定义的核心实现间的桥梁。

-- -------------------- ---- -------
----- ---------- - ------------
  -- --- --
  ---------------
    -----
    ------
    ----------------------
    ------------
    ----------------------
  - -
    -- ----- --- ------- -
      ------ ----------------------------
    -
    ----- --- ------------------ --------- ----- - - ------
  --

  -------------------
    -----
    ----------------------
    ------------
    ----------------------
  - -
    ------ ------------------------------
  --

  --------------------------- ------ -
    ----------------------------------
  --

  ------------------------- -
    ------ ------
  --

  ------------------ -
    ------ -----
  --

  ------------------ -
    ------ -----
  --
  -- --- --
---
展开代码

现在,我们可以使用 react-reconciler 渲染我们的组件了:

完成了这个例子,我们现在可以更深入地探讨一下 react-reconciler 的 API 和原理了。

React Reconciler API

Reconciler(options)

Reconciler 函数是我们构建自己的协调器的入口点。它接受一个 options 对象,它的属性列表如下:

  • createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle): 这个方法创建一个新的实例,表示特定类型的组件或原生控件。在浏览器中,这意味着创建一个 DOM 元素。React 使用这个方法跟踪组件结构,维护组件之间的关系,等等。

  • createTextInstance(text, rootContainerInstance, hostContext, internalInstanceHandle): 这个方法创建一个新的文本节点实例,用于表示 DOM 中的文本。React 将所有文本视为特殊类型的组件,因此如果您在组件中使用文本,React 将会调用这个方法来创建文本节点。

  • appendChild(parentInstance, child): 这个方法添加一个子元素到父元素中。在 React 中,这个方法表示将子元素添加到父元素的 children 属性中。

  • removeChild(parentInstance, child): 这个方法删除子元素从父元素中。React 使用这个方法来管理协调器内部的组件结构,以确保正确的协调和更新。

  • insertBefore(parentInstance, child, beforeChild): 这个方法将一个子元素插入到另一个子元素的前面。在 React 中,这通常在兄弟组件之间移动元素时使用。

  • finalizeInitialChildren(parentInstance, type, props, rootContainerInstance, hostContext): 这个方法获取一个组件的 props,并在组件被创建后调用。我们可以在这里修改初始化后的属性数据。例如,如果我们要为新组件设置默认值,则可以在这个方法中查找和确认所需的值。

  • prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, hostContext): 当组件更新时,React 会调用此方法,该方法允许我们比较 props 和以前的 props,并确定是否需要更新。如果我们确定组件不需要更新,则返回 null。

  • commitUpdate(instance, updatePayload, type, oldProps, newProps, internalInstanceHandle): 当组件需要更新时,React 将会调用此方法来执行真实的更新。在这里,我们可以使用之前计算出的更新内容,将其反映到真实的 DOM 上,或者在自定义的目标平台上反映更新。

  • prepareForCommit(containerInfo): 在 React 开始更新组件之前,我们可以在此方法中执行一些准备工作。例如,如果我们需要向自定义平台发送异步任务,则可以在这里处理并等待任务完成。

  • resetAfterCommit(containerInfo): 当 React 完成更新并已经成功渲染了 DOM(或自定义平台)时,此方法将会被调用。我们可以在这里进行一些在更新后运行的任务(例如动画等)。

Reconciler.createContainer(containerInfo[, isConcurrent[, hydrate]])

createContainer 方法创建一个新的协调器根节点。协调器节点对应了应用程序中的一个根 DOM 节点(或自定义平台等其他环境)。

  • containerInfo: 一个容器信息对象,该对象包含与 an 的 container 相关的特定信息。在 Web 上,这个就是一个 DOM 节点。

  • isConcurrent: 切换到 Concurrent 模式。

  • hydrate: 执行 Hydrate 模式。

Reconciler.updateContainer()

updateContainer 方法触发协调器更新。它类似于 ReactDOM.render 方法,但是它允许我们在多个时刻更新组件(例如,当应用程序状态改变时)。

示例代码

下面是一个完整的例子,其中我们将使用 react-reconciler 实现自己的协调器和组件。这个例子中,我们将在一个 WebGL 视口上绘制一个简单的方块。

-- -------------------- ---- -------
------ - ---------- - ---- -------------------

----- ---------- - ------------
  -- ------
  ------------------------------ ------------- -
    ----- -- - -----------------

    -- ----- ---
    ------ -
      --- ---
      -------- --------------
        ---
        -
          ---- ------ -
            ----------- - --------- ---- ---- -----
            ------------ - ------
          -
        --
        -
          ---- ------ -
            ------------ - --------- ---- ---- -----
          -
        -
      --
      --------------- ---------------- --- ---------------- -----
    --
  --

  -- ----
  -------------------- ------ ---------------------- ------------ ----------------------- -
    ----- -- - -------------------------

    -- ----- --- --------- -
      ------ -
        ----- -----
        ------ ----------- -- --- -- ---
        -------- ------------------------------
        --------------- -------------------------------------
      --
    -

    ----- --- ------------------ --------- ---- ----------
  --

  -- ----
  ----------------------- ----- --------- --------- ---------------------- ------------ -
    ------ ---------
  --

  -- ------
  ---------------------- -------------- ----- --------- --------- ----------------------- -
    -- ----- --- --------- -
      -------------- - -------------- -- --- -- ---
    -
  --

  -- -----
  --------------------------- ------ ---

  -- ---------
  --------------------------- ------ ---

  -- ------
  ------------------------ ---------------------- ------------ ----------------------- ---

  -- -----
  ------------------------- -
    ------ ------
  --

  -- ----
  ------------------ ---

  -- ----
  ------------------ ---

  -- ----
  -- -----------
  --------------------------- -
    ------ ------
  --

  -- ----------
  ---- ------ ----------- --- -------- - -- -- ----------------- - -- -- -----------
  ----------------- -----
  -------------------- ------
  ------------------ ------
---

-- -- ----- ---
----- ------ - ---------------------------------
----- -- - ---------------------------

-- -- ---------- ---
----- ---- - ----------------------------
  --- ---
---

-- -- ------ --
----- ------ - ---------------------------
  ----- ---------
  ------ --- -- ---
---

-- -- ------ -------
---------------------------- --------

-- -- ---------- ---
------------------------------ ----- ----- ------

-------- ----------------- --------- --------- -
  ----- -- - ----------------------------------
  ------------------- ----------
  ---------------------

  ----- -- - ------------------------------------
  ------------------- ----------
  ---------------------

  ----- ------- - -------------------
  ------------------------ ----
  ------------------------ ----
  ------------------------

  -- --------------------------------- ---------------- -
    ----- ------------- -----------------------------------
  -

  ------ --------
-

-------- ---------------- ----- -
  ----- ------ - ------------------
  ------------------------------ --------
  ------------------------------ ----- ----------------
  ------ -------
-
展开代码

这些代码将在 WebGL 上绘制一个简单的方块。这只是一个开始,并不算完整的实现,但它向您展示了如何使用 react-reconciler 实现自己的协调器,以及如何在自定义平台上渲染组件。

结论

React-reconciler 是 React 之外最为核心的一部分,它是在 React 基础上做自定义渲染、组件化UI以及Flash/flex等跨平台方向的催生器,这样在任何需要构建基于React编写的可视化程序的场景下都可以使用React即免于反复深入底层实现。在我们的实践中,我们可以使用 react-reconciler 创建自己的协调器。我们使用 MyRenderer 来实现绘制 WebGL 图形的协调器,来解释 react-reconciler 并提供了示例的深度文章。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/115274