如何在React中构建专用组件

时间:2019-04-05 15:53:11

标签: reactjs inheritance composition

我发现自己正在编写这样的代码,用于一堆具有某些共性的组件:

class PropertyBlock extends React.Component {
    render() {
        const { headtext, blockType, selectedId, selectOptions, onChange, extratext } = this.props
        return (
            <div className='propblk'>
                <div className='headline'>{headtext}</div>
                {blockType == 'dropdown' ? <PropBlk_Dropdown selectOptions={selectOptions} selectedId={selectedId} onChange={onChange} />
                    :
                    blockType == 'inp_line' ? <PropBlk_InputLine value={selectedId} onChange={onChange} />
                        :
                        blockType == 'inpstory' ? <PropBlk_InputStory value={selectedId} onChange={onChange} extratext={extratext} />
                            :
                            blockType == 'showline' ? <PropBlk_ShowLine value={selectedId} lines={selectOptions} />
                                :
                                blockType == 'inp_date' ? <PropBlk_InputDate value={selectedId} onChange={onChange} />
                                    :
                                    blockType == 'inp__chk' ? <PropBlk_Checkbox value={selectedId} onChange={onChange} extratext={extratext} />
                                        :
                                        <div>
                                            {selectedId}
                                        </div>

                }
            </div>
        )
    }
}

但是我以某种方式认为可能会更好。我在考虑一个parent组件和许多从该父级继承的专用child组件。喜欢:

class PropBlk_Type1 extends PropertyParentBlock {
   ...
}

但是,阅读On React似乎应该避免继承。所以我在React示例中尝试了以下方法:

class PropertyParentBlock extends React.Component {
    render() {
        const { headtext, myownhtml } = this.props
        return (
            <div className='propblk'>
                <div className='headline'>{headtext}</div>
                {myownhtml}
            </div>
        )
    }
}

class PropBlk_Type1 extends React.Component {
    render() {
        const { headtext, value, onChange, extratext } = this.props
        return (
            <PropertyParentBlock headtext={headtext}
                myownhtml={(
                    <div>
                        <input value={value} onChange={(e) => onChange(e.target.value)} />
                    </div>
                )}
            />
        )
    }
}

因此,专用html作为属性myhtml被加载到父组件中。使用WebPack构建它不会产生语法错误,并且实际上运行它会创建所需的html,并且似乎可以正常工作。

当我仍在学习React时,我想知道我是否走在正确的轨道上,或者对于这种继承或组合有更好的方法和最佳实践。

2 个答案:

答案 0 :(得分:1)

不需要像您一样嵌套三元运算符,您可以这样做:

class PropertyBlock extends React.Component {
    render() {
        const { headtext, blockType, selectedId, selectOptions, onChange, extratext } = this.props;
        let element;
        switch(blockType){
           case "dropdown" : 
               element =  <PropBlk_Dropdown selectOptions={selectOptions} selectedId={selectedId} onChange={onChange} />;
                 break;
            // go on here ...
        }
        return (
            <div className='propblk'>
                <div className='headline'>{headtext}</div>
                {element}
            </div>
        )
    }
}

答案 1 :(得分:0)

通过更仔细地阅读React文档,我发现自己处在正确的轨道上。通过省略一对括号并使用特殊的props.children可以简化我的示例。

我可以将问题的丑陋代码重写为类似“父”组件的东西:

class PropBlk_Frame extends React.Component {
    render() {
        const { headtext } = this.props
        return (
            <div className='propblk'>
                <div className='headline'>{headtext}</div>
                {this.props.children}
            </div>
        )
    }
}

上面的组件用于许多“子”组件,例如:

class PropBlk_InputLine extends React.Component {
    render() {
        const { headtext, value, inputfield, onChange } = this.props
        return (
            <PropBlk_Frame headtext={headtext}>
                <input value={value} onChange={(e) => onChange(true, e.target.value, inputfield)} onBlur={() => onChange(false, null, inputfield)} />
            </PropBlk_Frame>
        )
    }
}

class PropBlk_InputDate extends React.Component {
    render() {
        const { headtext, value, inputfield, onChange } = this.props
        return (
            <PropBlk_Frame headtext={headtext}>
                <input type='date' value={value} onChange={(e) => onChange(true, e.target.value, inputfield)} onBlur={() => onChange(false, null, inputfield)} />
            </PropBlk_Frame>
        )
    }
}

现在,我可以使用以下专用组件来构建我的网页:

<PropBlk_InputLine headtext='Projectnaam *' value={fields.ProjectNaam} inputfield='inp_projectnaam' onChange={this.onInput} />
<PropBlk_InputDate headtext='Opdrachtdatum *' value={fields.DatumLabOpdracht} inputfield='inp_opdrachtdatum' onChange={this.onInput} />

这种方法消除了三元结构,从而节省了代码行,并且更易于理解。