React拥有很强大的组合模型,我们建议使用组合来替代继承来重利用组件之间的代码。

在本章节中,我们将讨论一些开发者经常触及继承的问题,并且我们该如何使用组合来解决这些问题。

组合

一些组件事先不知道它们的子组件。这种问题特别对于组件类似Sidebar或者Dialog这种通用的“盒子”。

我们建议像这样的组件使用特殊的children属性去直接传递子元素到它们的输出里:

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>
);
}

在CodePen里试一试

任何在<FancyBorder>JSX标签的东西被作为一个children属性传递给FancyBorder组件。当FancyBorder组件在一个div里渲染了{props.children},传递来的元素会出现在最终的输出里。

然而很少有相同的情况,有时你也许需要在一个组件里有多个“入口”。在这样的情况下你也许会想出你自己的约定来替代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 />
} />
);
}

在CodePen里试一试

像<Contacts />和<Chat />这样的React元素都是对象,所以你可以就像其他数据一样将他们作为props传递。

特殊实例

有时某些组件会是其他组件的特殊情况。举个例子,我们可以说一个WelcomeDialog组件是Dialog组件的特殊情况。

在React里,这样的也是由组合来实现,一个更加“特殊的”组件会渲染一个更加“通用”的组件并且用props来配置它:

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!" />
);
}

在CodePen里试一试

组合对于定义为类的组件同样做得很好。

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}!`);
}
}

在CodePen里试一试

那么继承怎么样?

在Facebook网站,我们使用React制作了上千个组件,但是我们还未找到将会建议创建继承层次的情况。

props和组合给了你所有的灵活性来让你通过明确的和安全的方式自定义组件的样子和行为。记住组件可能接受任意props,包括简单的values,React elements或者函数。

如果你想要在组件之间复用与UI无关的功能,我们建议将它提取到一个单独的js模块里。这样可以在不对组件进行扩展的前提下导入并使用该函数、对象或类。

最新文章

  1. 第十四章:降维:奇异值分解SVD
  2. 2013长沙 G Graph Reconstruction (Havel-Hakimi定理)
  3. struts2:数据校验,通过Action中的validate()方法实现校验(续:多业务方法时的不同验证处理)
  4. Mysql 对数字的格式化
  5. [转载] 跟着实例学习zookeeper 的用法
  6. 第四周 课堂Scrum站立会议
  7. 关于js中的事件
  8. Apache Commons Pool2 源码分析 | Apache Commons Pool2 Source Code Analysis
  9. springmvc+mongodb+maven 项目测试代码
  10. makefile中&quot;:=&quot;,&quot;=&quot;,&quot;?=&quot;,&quot;+=&quot; 之间的区别
  11. javascript中对象字面量与数组字面量
  12. JavaScript闭包的深入理解
  13. 【linux】linux下vi命令的使用
  14. 安卓Eclipse开发者的福音
  15. 函数式编程之-拒绝空引用异常(Option类型)
  16. CSS中float属性
  17. FFmpeg libavutil主要功能概述
  18. 部署WEB项目到服务器(二)安装tomcat到linux服务器(Ubuntu)详解
  19. MapReduce全局变量之捉虫记
  20. hdu 4336 概率dp

热门文章

  1. kafka安装步骤
  2. centos7安装zabbix3.0超详细步骤解析
  3. lua语言中的假
  4. windows 如何创建硬链接
  5. python 竖排文本
  6. 爬虫----requests模块
  7. 【shell】wc命令
  8. 如何将数据库中的数据导入到Solr中
  9. Bugku-CTF之Web5(JSPFUCK??????)
  10. 剑指offer(22)从上往下打印二叉树