d3 v4 + react + ES6:如何以编程方式创建轴?

hur*_*rtz 6 d3.js ecmascript-6 reactjs

我试图在当前版本 4 中了解 d3。具体来说:我试图在 react 和 es6 中为简单的折线图创建 x 轴。

我看过 Mike Bostock 的例子以及他是如何做到的:

svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
Run Code Online (Sandbox Code Playgroud)

但这既不是 react 也不是 ES6。

在另一个站点上,我看到了以下变体:

renderAxis() {
  var node  = this.refs.axis;
  var axis = d3.svg.axis().orient(this.props.orient).ticks(5).scale(this.props.scale);
  d3.select(node).call(axis);
}

render() {
  return <g className="axis" ref="axis" transform={this.props.translate}></g>
}
Run Code Online (Sandbox Code Playgroud)

这是 React 和 ES6,但不是版本 4 中的 d3。

我可以尝试将第 3 版代码用于 d3 的第 4 版,但是: d3.select 非常困扰我。当我使用 react(或其中的其他库,如 d3)时,我不想进行 DOM 调用。React 应该用于以最有效的方式渲染到 DOM 中,而不是让我获取 DOM 节点。

所以,我的问题是:创建一个简单的 x 轴的反应方式是什么?或者,如果还没有这样的答案:采用 Mike Bostock 引用的代码的反应方式是什么?

Dom*_*cum 8

经过几年试图在 React 中找出 d3 之后,这是我和我的团队发现的最好的处理轴的方法:

const Axis = props => {
    const axisRef = axis => {
        axis && props.axisCreator(select(axis));
    };

    return <g className={props.className} ref={axisRef} />;
};
Run Code Online (Sandbox Code Playgroud)

笔记

  • axisCreator是由axisBottomaxisLeft等返回的函数。它是在组件外部创建的,目的是向用户展示 d3 轴库的全部功能。
  • className 允许用户随意设置轴的样式。
  • 此示例使用 refs,React 文档警告不要使用 refs,但它使用 refs 与第三方 DOM 库集成,这也是使用 React 文档专门调用的 refs 的原因之一
  • 使用 d3 的select麻烦是可以理解的,但是如果你想让 d3 操作 DOM,它是必需的,如果你不让 d3 操作 DOM,你就失去了 d3 的所有功能(这是一个非常 酷的 库))。


小智 5

如果您正在使用 React,那么您几乎可以控制 DOM 的工作方式,因为它是内部工作的。React 将在虚拟 DOM 树中渲染你的组件,然后找出页面中的 DOM 树在你插入根组件时和前者之间的区别。它将应用两棵树之间的差异,以便页面中的树看起来像虚拟树。

混合 d3 和 React 需要一些技巧。你使用 d3 的所有元素(节点或属性)不应该归 React 所有。否则会发生奇怪的事情。假设您transformg.axis节点属性由 d3 设置,这意味着您不在 React 中渲染它。你让你的 d3 逻辑拥有它的独占所有权。

现在是下一步。如果您想使用其他工具来描述 DOM 节点,那么您必须将该逻辑放在componentWillMount和 中componentDidUpdate。基本上你只在Reactgrender()方法中渲染元素,然后在这两个 React 生命周期句柄中你可以改变g元素的属性和里面的内容。

我将向您指出这篇文章,文章更详细地介绍了方法,但我也想给我两分钱。从我对这两个函数的角度和经验来看,最好只将 d3 用于它的辅助函数(通用数学函数)。让渲染逻辑(DOM 组合)完全在 React 中完成,即使会出现代码重复。维护一致且没有两种不同渲染方法混合在一起的代码更容易。

TL; 博士; 将属性或节点所有权赋予 React 或 d3,以便它们一起工作;或者我的建议,在 React 中制作您自己的轴组件,输出与 d3 相同的 DOM 元素(或者如果您需要其他功能或样式,则不同)并且不要使用 d3 进行渲染。

希望我有所帮助。