在文档片段中呈现React树的一部分以避免呈现DOM节点

时间:2016-12-02 16:21:58

标签: javascript reactjs canvas

在某些情况下,我想在不渲染实际DOM节点的情况下使用React。例如,当使用<canvas>时,最好能够将子项添加到画布中,如下所示:

<canvas>
    <Rectangle>
        <Circle />
    </Rectangle>
<canvas>

<Rectangle /><Circle />可以通过将其作为道具或上下文传递来访问canvas元素,并且可以使用componentDidMountcomponentDidUpdate在其上绘制

有些库可以执行类似react-pixireact-three之类的操作,但是它们会对内部函数的反应造成很大的影响。

起初我很难,我可以让<Rectangle /><Circle />的渲染功能返回this.props.childrennull,但如果有些孩子,这种做法不会起作用是一个数组。然后需要将其包装在元素中。

例如,如果<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>节点没有被真正修改。

这是个好主意吗?我和魔鬼一起玩吗?

由于

0 个答案:

没有答案