014-组合与继承
一、概述
React具有强大的组合模型,我们推荐使用组合而不是继承来重用组件之间的代码。
1.1、遏制
有些组件不提前知道他们的子组件。这对于代表像Sidebar
或Dialog
通用“盒子”的组件尤其常见。
建议这些组件使用特殊的children prop
将子元素直接传递到它们的输出中:
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-message"> Thank you for visiting our spacecraft! </p> </FancyBorder> ); }
<FancyBorder> JSX标签内的任何内容都将作为children prop传递到FancyBorder组件。由于FancyBorder
渲染{props.children}
内部<div>
,传递的元素出现在最终的输出中。
虽然这种情况不太常见,但有时您可能需要在组件中出现多个“漏洞”。在这种情况下,你可以拿出你自己的约定,而不是使用children
:
function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); }
像<Contacts />和<Chat />这样的React元素只是对象,所以你可以像任何其他数据一样将它们作为prop来传递。这种方法可能会提醒您其他库中的“插槽”,但对于您可以在React中传递的prop没有限制。
1.2/专业化
有时我们会将组件视为其他组件的“特例”。例如,我们可以说一个WelcomeDialog是Dialog的特例。
在React中,这也可以通过组合来实现,其中一个更“特定”的组件呈现更“通用”的组件,并使用prop进行配置:
function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); } function WelcomeDialog() { return ( <Dialog title="Welcome" message="Thank you for visiting our spacecraft!" /> ); }
对于定义为类的组件,组合的作用同样好:
function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> {props.children} </FancyBorder> ); } class SignUpDialog extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.handleSignUp = this.handleSignUp.bind(this); this.state = {login: ''}; } render() { return ( <Dialog title="Mars Exploration Program" message="How should we refer to you?"> <input value={this.state.login} onChange={this.handleChange} /> <button onClick={this.handleSignUp}> Sign Me Up! </button> </Dialog> ); } handleChange(e) { this.setState({login: e.target.value}); } handleSignUp() { alert(`Welcome aboard, ${this.state.login}!`); } }
那么继承呢?
在Facebook上,我们在数千个组件中使用React,并且我们还没有发现任何建议创建组件继承层次结构的用例。
prop和组合为您提供了所有需要的灵活性,以明确和安全的方式自定义组件的外观和行为。请记住,组件可以接受任意prop,包括原始值,React元素或函数。
如果您想在组件之间重用非UI功能,我们建议将其解压缩到单独的JavaScript模块中。组件可以将其导入并使用该函数,对象或类,而不对其进行扩展。