React ——究竟是应该使用组合还是继承?

本文探讨了React中组件设计的两种核心模式:组合与继承。强调了使用组合而非继承来实现组件间代码重用的重要性,并通过具体示例展示了如何利用props传递子组件及定制组件的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组合 vs 继承

React 有十分强大的组合模式。我们推荐使用组合而非继承来实现组件间的代码重用。

包含关系

有写组件无法提前知晓它们的子组件的具体内容。在Sidebar(侧边栏)和Dialog(对话框)等展示通用容器(box)的组件中特别容易遇到这种情况。
我们们建议这些组件使用一个特殊的childrenprop来将他们的子组件传递到渲染结果中:

function FancyBorder(props){
    return (
        <div className={'FancyBorder FancyBorder-' + props.color}>
            {props.children}
        </div>
    )
}

这使得别的组件可以通过jsx嵌套,将任意组件作为子组件传递给他们。

function WelcomeDialog(){
    return (
        <FancyBorder color="blue">
            <h1 className="Dialog-title">welcome</h1>
            <p className="Dialog-messagge">
                Thank you for visiting our spacecraft!
            </p>
        </FancyBorder>
    )
}

<FancyBorder>jsx标签中的所有内容都会作为一个childrenprop传递给<FancyBorder>组件。因为FancyBorder{props.children}渲染到一个div中,被传递的这些子组件最终都会出现在输入结果中。
少数情况下,你可能需要在一个组件中中预留出几个“洞”。这种情况下,我们可以不适用children,而自行约定:将所需内容传入props,并使用相应的prop。

function SplitPane (props) {
    return (
        <div className="SplitPane">
            <div className="SplitPane-left">{props.left}</div>
            <div className="SplitPane-right">{props.right}</div>
        </div>
    )
}

function App () {
    function Left () {
        return (
            <div>left</div>
        )
    }

    function Right () {
        return (
            <div>right</div>
        )
    }

    let Left1 = <div>left1</div>;
    let Right1 = <div>Right1</div>;
    return (
        <div>
            <SplitPane left={<Left />} right={<Right />} />
            <SplitPane left={Left1} right={Right1} />
        </div>

    )
}

、 和 Left1 、Right1 是React元素和jsx对象,本质上都是js的对象,所以可以把它们当做props,像其他数据一样传递。这种方法可能使你想起别的库中“槽”(slot)的概念,但是在React中没有“槽”这个概念的限制,你可以将任何东西座位props进行传递。

特例关系

有时候,我们会把一些组件看做其他组件的椰树实例,比如WelcomeDialog可以说是Dialog的特殊实例。
在React中,我们也可以通过组合来实现这一点。“特殊组件”可以通过props定制并渲染“一般”组件。

function Dialog (props) {
    return (
        <div color="blue">
            <h1 className="Dialog-title">{props.title}</h1>
            <p className="Dialog-messagge">
               {props.message}
            </p>
        </div>
    )
}


function WelcomeDialog () {
    return (
        <Dialog color="blue" title="welcome" message="thank you for visiting our home " />
    )
}

组合也同样使用于以class形式定义的组件。

function Dialog (props) {
    return (
        <div color="blue">
            <h1 className="Dialog-title">{props.title}</h1>
            <p className="Dialog-messagge">
               {props.message}
            </p>
            {props.children}
        </div>
    )
}


class SignUpDialog extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            login:""
        }
    }
    handleChange= (e)=>{
        this.setState({
            login:e.target.value
        })
    }
    handleClick=()=>{
        alert(`welcome aboard,${this.state.login}`)
    }
    render(){
        return (
            <Dialog title="title" message="message">
                <input type="text" value={this.state.login} onChange={this.handleChange}/>
                <button onClick={this.handleClick}>sign up</button>
            </Dialog>
        )
    }
}

那么继承呢?

在Facebook,我们在成百上千个组件使用React。我们并没有发现需要使用继承来构建组件层次的情况。
props和组合为你提供了清洗而安全地定制组件外观和行为的灵活方式。注意组件可以接受任意的props,包括寄出数据类型,React元素以及函数。
如果你想要在组件间复用非ui的功能,我们建议将其提取成一个单独的JavaScript模块,如函数、对象或者类。组件可以直接映入(import)而无需通过extend继承他们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值