在某些情况下,我想在不渲染实际DOM节点的情况下使用React。例如,当使用<canvas>
时,最好能够将子项添加到画布中,如下所示:
<canvas>
<Rectangle>
<Circle />
</Rectangle>
<canvas>
<Rectangle />
或<Circle />
可以通过将其作为道具或上下文传递来访问canvas元素,并且可以使用componentDidMount
和componentDidUpdate
在其上绘制
有些库可以执行类似react-pixi或react-three之类的操作,但是它们会对内部函数的反应造成很大的影响。
起初我很难,我可以让<Rectangle />
或<Circle />
的渲染功能返回this.props.children
或null
,但如果有些孩子,这种做法不会起作用是一个数组。然后需要将其包装在元素中。
例如,如果<Rectangle />
和<Circle />
渲染函数如下所示:
render: function()
{
return this.props.children || null;
}
这不会起作用
<canvas>
<Rectangle>
<Circle />
<Circle />
</Rectangle>
<canvas>
所以我已经找到了使用文档片段的解决方案。
首先,有一个顶级FragmentTree
组件需要在<canvas>
内包装任何内容。
这样的事情:
var React = require('react');
var ReactDOM = require('react-dom');
var FragmentTree = React.createClass({
getInitialState: function()
{
var fragment = document.createDocumentFragment();
var rootNode = document.createElement('div');
fragment.appendChild(rootNode);
return {
fragment: fragment,
rootNode: rootNode
};
},
render: function()
{
return null;
},
componentDidMount: function()
{
if (this.props.children) {
this.renderChildren();
}
},
componentDidUpdate: function(prevProps, prevState)
{
var elementChanged = this.state.element !== prevState.element;
var childrenChanged = this.props.children !== prevProps.children;
if (elementChanged || (this.props.children && childrenChanged)) {
this.renderChildren();
}
},
renderChildren: function()
{
var fragment = this.state.fragment;
var rootNode = this.state.rootNode;
var children = React.Children.map(this.props.children, function(child)
{
return React.cloneElement(child, {
_fragment: fragment,
_parentNode: rootNode
});
});
var element = React.createElement('div', null, children);
ReactDOM.render(element, rootNode);
}
});
module.exports = FragmentTree;
然后,有一个组件包含FragmentTree
内的任何组件。这是一家工厂。
var React = require('react');
function createFragmentTreeElement(Component)
{
var FragmentTreeElement = React.createClass({
render: function()
{
if (_.isArray(this.props.children)){
return (
<Component {...this.props}>
<div>
{ this.props.children }
</div>
</Component>
);
}
return (
<Component {...this.props}>
{ this.props.children }
</Component>
);
}
});
return FragmentTreeElement;
}
module.exports = createFragmentTreeElement;
所以&#34;假&#34;组件的创建方式如下:
var Rectangle = React.createClass({
render: function()
{
return this.props.children || null;
},
componentDidMount: function()
{
//Draw the rectangle
},
componentDidUpdate: function()
{
//Update the rectangle
}
});
module.exports = createFragmentTreeElement(Rectangle);
然后这将有效:
<canvas>
<FragmentTree>
<Rectangle>
<Circle />
<Circle>
<Circle />
</Circle>
</Rectangle>
</FragmentTree>
<canvas>
它似乎工作得非常好,因为任何组件都能正常运行。此外,内存和处理应该是最小的,因为它在文档片段中呈现并且包装<div>
节点没有被真正修改。
这是个好主意吗?我和魔鬼一起玩吗?
由于