简体   繁体   English

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

[英]d3 v4 + react + ES6: How to create axis programmatically?

I am trying to get my head around d3 in its current version 4. Specifically: I a trying to create the x axis for a simple line chart in react and es6. 我试图在当前版本4中绕过d3。具体来说:我试图为react和es6中的简单折线图创建x轴。

I have seen the examples of Mike Bostock and how he does it: 我已经看过Mike Bostock的例子以及他是如何做到的:

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

But that is neither react nor ES6. 但这既不是反应也不是ES6。

On another site I have seen the following variant: 在另一个网站上,我看到了以下变体:

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>
}

This is react and ES6 but not d3 in version 4. 这是反应和ES6,但不是版本4中的d3。

I could try to adopt the version 3 code to version 4 of d3 but: The d3.select bothers me extremely. 我可以尝试将版本3代码用于d3的第4版但是:d3.select非常困扰我。 I don't want to make DOM-calls when I am using react (or some other library within, like d3). 当我使用react(或者其他一些库,比如d3)时,我不想进行DOM调用。 React should be used to render into the DOM in the most efficient way, not to get me DOM nodes. 应该使用React以最有效的方式呈现到DOM中,而不是让我获得DOM节点。

So, my question is: What is the react-way to create me a simple x axis? 所以,我的问题是:创建一个简单的x轴的反应方式是什么? Or, if there is yet not such an answer: What is the react way to adopt the quoted code of Mike Bostock? 或者,如果还没有这样的答案:采用Mike Bostock引用代码的反应方式是什么?

If you are using React then you are pretty much giving control of how the DOM works to React because of it's internal workings. 如果您正在使用React,那么您几乎可以控制DOM如何工作到React,因为它的内部工作原理。 React will render your components inside a virtual DOM tree and then figure out the difference between the DOM tree in the page were you inserted the root component and the former. React会将您的组件呈现在虚拟DOM树中,然后在插入根组件和前者时,找出页面中DOM树之间的差异。 It will apply the difference between the two trees so that the tree in the page will look like the virtual one. 它将应用两棵树之间的差异,以便页面中的树看起来像虚拟树。

Mixing d3 and React requires a bit of a trick. 混合d3和React需要一些技巧。 All the elements you use d3 for (nodes or attributes) should not be owned by React. 您使用d3(节点或属性)的所有元素都不应归React所有。 Otherwise weird stuff happens. 否则会发生奇怪的事情。 Let's say your transform attribute for the g.axis node is set by d3, that implies that you don't render it in React. 假设你的g.axis节点的transform属性是由d3设置的,这意味着你不在React中渲染它。 You let your d3 logic have exclusive ownership of it. 你让你的d3逻辑拥有它的独家所有权。

Now comes the next step. 现在是下一步。 If you want to use other tools to describe DOM nodes then you got to put that logic inside componentWillMount and componentDidUpdate . 如果您想使用其他工具来描述DOM节点,那么您必须将该逻辑放在componentWillMountcomponentDidUpdate Basically you only render the g element inside the render() method of React and then inside those two React lifecycle handles you can change the attributes of the g element and what's inside. 基本上你只在React的render()方法中渲染g元素,然后在这两个React生命周期句柄中你可以改变g元素的属性和里面的内容。

I will point you towards this post that goes a bit more in detail about the hows , but I would also like to give my two cents. 我将指出你对这篇关于这些方法更详细的文章 ,但我也想给我两分钱。 From my perspective and experience with these two it is best to only use d3 for it's helper functions (generic math functions). 根据我对这两者的看法和经验,最好只使用d3作为辅助函数(通用数学函数)。 Let the rendering logic (DOM composition) be done purely in React even though there's code duplication that arises. 让渲染逻辑(DOM组合)完全在React中完成,即使出现了代码重复。 It is way easier to maintain code that is consistent and that doesn't have two different approaches to rendering mixed together. 维护一致的代码并且没有两种不同的渲染混合方法更容易。

TL;DR; TL; DR; Either give attributes or nodes ownership to either React or d3 for them to work together; 将属性或节点所有权赋予React或d3以使它们一起工作; or my recommendation, make your own axis component in React that outputs the same DOM elements as the d3 one (or different if you desire other functionality or style) and don't use d3 for rendering. 或者我的建议,在React中创建自己的轴组件,输出与d3相同的DOM元素(如果需要其他功能或样式,则输出不同),不要使用d3进行渲染。

Hope I helped. 希望我帮忙。

After a couple years of trying to figure out d3 in React, this is the best way my team and I have found of doing axes: 经过几年试图在React中找出d3,这是我的团队和我发现做轴的最佳方式:

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

    return <g className={props.className} ref={axisRef} />;
};

Notes 笔记

  • axisCreator is the function returned by axisBottom , axisLeft , etc. It is created outside the component to expose to the user the full power of the d3-axis library. axisCreatoraxisBottomaxisLeft等返回的函数。它在组件外部创建,以向用户显示d3轴库的全部功能。
  • className allows the user to style the axis however he or she wants. className允许用户根据自己的需要设置轴的样式。
  • This example uses refs, which the React docs caution against , but it uses refs to integrate with a third-party DOM library, which is one of the reasons to use refs that the React docs call out specifically . 此示例使用refs, React文档警告 ,但它使用refs与第三方DOM库集成,这是使用React文档专门调用的引用的原因之一
  • It is understandable that using d3's select bothers you, but it's required if you want to let d3 manipulate the DOM, and if you don't let d3 manipulate the DOM, you lose out on all the functionality of d3 (which is an incredibly cool library ). 使用d3的select困扰你是可以理解的,但如果你想让d3操纵DOM,那么它是必需的,如果你不让d3操纵DOM,你就会失去d3的所有功能(这是非常 酷的 图书馆 )。

The code for rendering axis using React directly, rather than d3's select API, is actually not that complex. 直接使用React而不是d3的select API渲染轴的代码实际上并不复杂。 react-d3-axis provides a pretty simple, ~100 loc implementation. react-d3-axis提供了一个非常简单的~100 loc实现。 Going this approach lets you use d3 for stuff like data transformations and scale interpolation, and use React for rendering. 通过这种方法,您可以将d3用于数据转换和比例插值等操作,并使用React进行渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM