我目前正在使用react来创建d3可视化。我对render
和componenetDidMount
方法之间的关系感到有点困惑(方法是正确的术语吗?)。这就是我所拥有的(为简单起见,我排除了一些代码):
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,但是如何在VirtualDOM上选择更多内容呢?
第二个问题:我知道,鉴于我对此很陌生,我可能做错了。你能在这里建议一个更好的方法吗?
第三个问题:我想在div
的兄弟".Chart"
中添加图表图例。我应该为此创建一个新组件吗?或者在我的d3Chart中,我可以使用选择器来执行此操作吗?
提前感谢您的帮助!
P.S。我有一个问题:
我已经看到人们使用React.render(<Chart />,document.body)
而不是使用React.createElement
。有人可以向我解释一下这个区别吗?
答案 0 :(得分:8)
是的,getDOMNode()
返回render
编辑的最外层DOM元素。
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);
答案 1 :(得分:2)
只是一个注释......从v0.13开始。 componentDidMount()
可能尚未提供this.refs
。来自更改日志:
ref
解析顺序略有变化,以便在调用componentDidMount
方法后立即获得对组件的引用;只有当您的组件在componentDidMount
内调用父组件的回调时,才能观察到此更改,这是一种反模式,无论如何都应该避免
答案 2 :(得分:1)
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>
);
}
}
答案 3 :(得分:0)
请注意,自React v15.0 getDOMNode()
起删除(自v0.13以后已弃用)且无法再使用。
编辑:在以下答案中有关于getDOMNode()
的弃用和React.findDOMNode(component)
的介绍(您应该使用)的详细说明:
https://stackoverflow.com/a/30191683/6223301
答案 4 :(得分:-1)
渲染从父级转移到childrem。因此,componentDidMount
可能没有refs
子节点而是放置setTimeout
函数,因此所有子节点都被渲染,refs可用于操作