【问题标题】:Confuse about the overlap and collision between React and D3混淆 React 和 D3 之间的重叠和碰撞
【发布时间】:2016-02-02 23:28:03
【问题描述】:

全部:

我对 React 还很陌生,我想做的是将 D3 数据可视化图表转换为 React 组件,但有一个令人困惑的地方:

我不太了解React的virtualDOM,但我相信有一点是D3不能直接对其进行操作(只有真实的DOM才能被D3操作,对吧?),那么问题来了:

我们如何才能充分利用 React?如果这不是真的,谁能给我看一些同时使用 D3 和 virtualDOM 的代码来制作具有数据更新操作和动画转换的图表

谢谢

【问题讨论】:

    标签: d3.js reactjs


    【解决方案1】:

    你说得对,D3 不在 React 的虚拟 DOM 上运行,因此 D3 与 react 不直接兼容。这很不幸,但基本上有两种解决方法。

    1) 使其在虚拟 dom 上运行。 react-faux-dom 在这方面做得很好,并且使很多 D3 工作在 react 的上下文中变得有意义。 https://github.com/Olical/react-faux-dom

    2) 使用逃生舱口,直接操纵 dom。本质上,拦截componentWillReceiveProps 中的新道具并将shouldComponentUpdate 设置为始终返回false。从那里,从componentWillRecieveProps 获取数据,然后使用 dom refs 对 d3 元素执行您想要的操作。

    这两种情况都不是特别漂亮。在 React 应用程序中执行 D3 还没有完美的解决方案。

    【讨论】:

    • 谢谢,所以说如果我们忘记了 D3 DOM 操作,就留下它的数学部分,你能告诉我如何像在 D3 中那样使用过渡动画来操作那些 virtualDOM?
    • 如果您使用的是react-faux-dom,那么使用react-motion 可能会有一些运气。如果您使用的是逃生舱口,那么一切都应该像在 react 之外一样工作,因此您可以像不在 react 应用程序中一样做您想做的事情。你只需要小心。
    【解决方案2】:

    我发现最简单的做法是使用componentDidMount() 在 React 组件中加载 d3 可视化。然后,您可以(在 d3 代码中)访问 React 属性和状态,在它们之间来回传递数据。 Here is an example.

    【讨论】:

      【解决方案3】:

      有一种方法可以让 React 处理真正的 SVG 元素,而 D3 只做数学运算。来自网络的例子:

      class Line extends React.Component {
          static contextTypes = {
              xScale: React.PropTypes.func,
              yScale: React.PropTypes.func
          };
      
          render() {
              let path = d3.svg.line()
                               .interpolate("linear")
                               .x(d => this.context.xScale(d.x))
                               .y(d => this.context.yScale(d.y));
      
              return (
                  <path d={path(this.props.data)}
                        stroke="#0077CC"
                        strokeWidth="3"
                        fill="none" />
              );
          }
      }
      
      class Chart extends React.Component {
          static propTypes = {
              width: React.PropTypes.number,
              height: React.PropTypes.number,
              data: React.PropTypes.shape({
                  x: React.PropTypes.number.isRequired,
                  y: React.PropTypes.number.isRequired
              }).isRequired
          };
      
          static defaultProps = {
              width: 400,
              height: 200
          };
      
          static childContextTypes = {
              xScale: React.PropTypes.func,
              yScale: React.PropTypes.func
          };
      
          getChildContext() {
              return {
                  xScale: this.getXScale(),
                  yScale: this.getYScale()
              }
          }
      
          getXScale() {
              return d3.scale.linear()
                       .domain(d3.extent(this.props.data, d => d.x))
                       .range([0, this.props.width]);
          }
      
          getYScale() {
              return d3.scale.linear()
                       .domain(d3.extent(this.props.data, d => d.y))
                       .range([this.props.height, 0]);
          }
      
          render() {
              return (
                  <svg style={{ width: this.props.width, height: this.props.height }}>
                      <Line data={this.props.data} />
                  </svg>
              );
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 2015-04-23
        • 1970-01-01
        • 2015-08-09
        • 2013-03-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多