ReactJS componentDidMount + 渲染

ReactJS componentDidMount + render

我目前正在使用 React 创建 d3 可视化。我对 rendercomponenetDidMount 方法之间的关系有点困惑(方法是正确的术语吗?)。这是我所拥有的(为简单起见,我排除了一些代码):

var Chart = React.createClass({
  componentDidMount: function () {
    var el = this.getDOMNode();
    console.log(el);
    d3Chart.create(el, {
        width: '500',
        height: '300'
    }, this.getChartState(),this.getAccessState);
  },

  render: function () {
    return (
        <div className="row pushdown">
                <div className="d3-block">
                    <div className="Chart" />
                </div>
        </div>
    );
  }
}

在第 3 行,el 被赋值 this.getDOMNode();,它始终指向渲染函数中的顶级元素 (div "row pushdown")。那么 this.getDOMNode() 是否总是引用渲染函数中的顶级元素?我实际上想做的是在最里面的 div (.Chart) 内渲染 d3 图表。我首先尝试做 this.getDOMNode().find('.Chart') 但那没有用。

第一个问题:我知道我不应该在这里尝试触摸真实的 DOM,但是我如何才能在虚拟DOM 上进一步选择一些东西?

第二个问题:我知道,鉴于我对此很陌生,我可能做错了。你能在这里推荐一个更好的方法吗?

第三个问题:我想在 ".Chart" 的兄弟 div 中添加图表图例。我应该为此创建一个新组件吗?或者在我的 d3Chart 中我可以使用选择器来做到这一点吗?

提前感谢您的帮助!

P.S。我有一个问题:

我看到人们在其中使用 React.render(<Chart />,document.body) 而不是 React.createElement。有人能给我解释一下区别吗?

是的,getDOMNode() returns 最外面的 DOM 元素 rendered。

A1。我建议您使用 ref 属性 (documentation),它提供对 DOM 元素的引用供以后使用:

<div ref="chart" className="Chart" />

componentDidMount: function() {
    // << you can get access to the element by name as shown below
    var chart = this.refs.chart; 
    // do what you want here ...
}

A2。虽然最终您可能希望将代码重构为多个组件,但您创建的内容没有任何问题(假设您尝试了上面提到的 ref 选项)。

A3。由于图例代表了一个非常不同的功能(并且是孤立的),因此创建一个独特的组件将是典型的 React。您可能仍然有一个 Chart 组件,它既包含实际图表可视化,也包含另一个显示图例的组件。这是一个很好的关注点分离。但是,您也可以考虑一个 Flux 模型,其中每个组件都监听变化并完全独立地呈现其视觉效果。如果它们紧密合作,Flux 模型可能就没有那么大的意义了。

侧面:使用 JSX,您可能会看到:

React.render(<App />, document.body)

这只会将 App 渲染到文档正文内容中。

相当于预编译的 JSX:

React.render(React.createElement(App, null), document.body);

请注意...从 v0.13 开始。 componentDidMount() 可能还没有 this.refs 可用。来自更新日志:

ref 解析顺序略有改变,组件的 ref 在 componentDidMount 方法被调用后立即可用;仅当您的组件在 componentDidMount 中调用父组件的回调时,才应观察到此更改,这是一种反模式,无论如何都应避免

渲染从 parent 变为 childrem。所以 componentDidMount 可能没有 refs 到 child 节点,而是放置 setTimeout 函数,所以所有 child 节点都被渲染并且 refs 将可用于操作

请注意,从 React v15.0 开始,getDOMNode() 已被删除(自 v0.13 起已弃用)并且不能再使用。

编辑:在以下答案中对 getDOMNode() 的弃用和 React.findDOMNode(component) 的引入(您应该改用)进行了详尽的解释:

this.refs 非常适合使用 ReactDOM 库在反应组件生命周期中找到任何 dom 节点。使用 NPM 安装 react-dom 或在您的页面中包含 JS。

因此您的整个组件代码应如下所示:

import React from 'react';
import ReactDOM from 'react-dom';

var Chart = React.createClass({
  componentDidMount: function () {
    var el = ReactDOM.findDOMNode(this.refs.chartComp);
    console.log(el);
    d3Chart.create(el, {
        width: '500',
        height: '300'
    }, this.getChartState(),this.getAccessState);
  },

  render: function () {
    return (
        <div className="row pushdown">
                <div className="d3-block">
                    <div ref="chartComp" className="Chart" />
                </div>
        </div>
    );
  }
});