图表更新如何在 React 上下文中工作?

How does chart updating works within the context of react?

我目前在 chart.js 中使用 React 集成有一个雷达图。

我惊讶地注意到,当我更新数据时,它并没有显示一个全新的图,它只是从以前的数据集平滑地过渡到新的数据集。

我感兴趣的是了解它在幕后是如何工作的,老实说我无法理解,至少从代码来看是这样。

首先:我对React的理解是,当一个prop或state发生变化时,它会计算出新的DOM,然后合并新的DOM和当前的DOM,仅应用两者之间的差异。但是,chartjs 似乎是作为 Canvas 元素实现的。

chartjs 与 react 的集成作用不大。以雷达图为例,this is what it does

export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);

这只是声明一个 <Chart> 元素并将其留给 ChartJS 来绘制它。事实上,在 ChartJS 中,we have this code,它基本上管理着 Canvas 元素,并且使用动画等来执行转换是很聪明的。这个我理解(相对):很多动画和过渡辅助函数,但这对我来说很有意义。然而,这部分是纯粹的JavaScript。没有任何关于 React 的知识。

因此,没有意义的是反应同步系统如何与这个 JavaScript 库集成,以便 props/state 的状态失效同步到动画,而不是完全重写Canvas 元素的。我似乎没有在 react-chartjs-2 中找到这种魔法发生的地方。

你可以在这里看到:https://github.com/reactchartjs/react-chartjs-2/blob/master/src/chart.tsx

react-chartjs-2 库创建了一个添加 canvas 的组件,当道具更新组件时 creates/updates 使用呈现的 canvas 的内部图表对象.

据我所见,当道具改变时动画开始。

路径为props->react-chartjs-2组件->图表对象->动画

正如您所解释的那样,canvas 元素不会更改,因此会被重复使用。动画图表 chart.js 本身有一个更新方法。 React-chartjs-2 使用useeffect 函数来检查您传递给它的数据是否已更改。如果是这种情况,它会从 chart.js 本身调用更新函数,它们会处理动画并自行更新:

  useEffect(() => {
    if (!chartRef.current) return;

    if (redraw) {
      destroyChart();
      setTimeout(renderChart);
    } else {
      chartRef.current.update();
    }
  }, [redraw, options, data.labels, data.datasets]);

https://github.com/reactchartjs/react-chartjs-2/blob/4a010540ac01b1e4b299705ddd93f412df4875d1/src/chart.tsx#L78-L87

这是我深入研究代码库后对整个过程的理解。我试图尽可能详细地提供指向我正在谈论的确切代码行的链接。希望这会有所帮助:

  1. 从您分享的代码片段开始:

    export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);

  2. 如果你关注 RadarController via the import statement,你会看到它是从 chart.js

    中获取的
  3. 现在我们转到 Chart.js 代码并查找此控制器 RadarController。它位于名为 src/controllers/controller.radar.js.

    的文件中
  4. 在该文件中,您会看到 update function

  5. 这个函数然后calls updateElements加上积分信息

  6. 这个函数得到new point position which is then set in properties and passed into the updateElement function

  7. 这个 updateElement 函数直接把我们带到 core.datasetController

  8. 在这里您可以看到检查图表是否处于 directUpdateMode 的条件。如果不是,它会调用 function to _resolveAnimations

  9. 在此函数中,您将看到 new Animations(args) object

  10. 这最终将我们带到了 core.animations file,其中包含所有与动画相关的信息和处理。

  11. 我在这里发现的一个有趣的地方是:this 似乎是使点的美丽移动到已更改的位置。

  12. 您可以进一步探索此动画class以获得更详细的理解

所以,是的,本质上,是引擎盖下的 js 部分促进了平滑过渡,这就是它的实现方式。 React 代码本质上就像 Chart.js 的包装器,使用新值调用此更新方法。