react 提倡使用组合而不是继承来复用代码,具体原因呢,我现在还不知道-_-!
好,先看看什么情况下我们会用到组合:
1. 包含关系:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
这个FancyBorder组件用到了props.children
属性,这个属性通常情况下表示的是<FancyBorder> </FancyBorder>
两个标签内的任何东西,那我们可能会想到,如果我们给这个组件传入一个children
属性会怎么样呢?
经过测试,发现children属性还是组件内的内容,而不是组件的属性值,后来我看了一下网友的分享,就是当
<FancyBorder> </FancyBorder>
这个标签内没有任何东西的时候,props.children
才代表的是组件传入的children属性值。
由于是包含关系,我们就可以直接把子组件传入到父组件内部,就像我们上面写的那样
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
我们这个WelcomeDialog
就是包含一个FancyBorder
,我们给他传入子组件,然后这个FancyBorder
还是会正确的渲染出来,从而实现了代码的复用。
现在我们只能通过props.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 是两个自定义组件,没有写出来)两个部分来传递子组件,如果我们继续用props.children
的话,是不是就不好实现了呢?
2. 特殊实例
如果我们有一个组件仅仅是一个通用组件传入了某个特殊的属性值,那么这个组件就是特殊实例,我们可以通过组合的方式实现:
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!" />
);
}
可以看到这个WelcomeDialog
就是Dialog
的特殊实例
当然这些对于用es6 class
方式定义的组件同样适用。
说了这么多组合的用法,那我们怎么使用继承呢?
好吧,官网应该是对继承深恶痛绝。
在 Facebook 网站上,我们的 React 使用了数以千计的组件,然而却还未发现任何需要推荐你使用继承的情况。
属性和组合为你提供了以清晰和安全的方式自定义组件的样式和行为所需的所有灵活性。请记住,组件可以接受任意元素,包括基本数据类型、React 元素或函数。
如果要在组件之间复用 UI 无关的功能,我们建议将其提取到单独的 JavaScript 模块中。这样可以在不对组件进行扩展的前提下导入并使用该函数、对象或类。
可能是因为JSX
的灵活性吧