diff --git "a/React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\345\220\210\344\270\216\347\273\247\346\211\277.md" "b/React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\345\220\210\344\270\216\347\273\247\346\211\277.md" new file mode 100644 index 0000000..56468d5 --- /dev/null +++ "b/React\351\235\242\351\235\242\350\247\202/\343\200\220\350\257\221\343\200\221\345\277\253\351\200\237\350\265\267\346\255\245-\347\273\204\345\220\210\344\270\216\347\273\247\346\211\277.md" @@ -0,0 +1,170 @@ +--- +title: 快速起步-组合与继承 +date: 2017-4-26 13:19:51 +version: 15.5.0 +--- + +# 组合 VS. 继承 + +`React` 具有很强大的组合模型,我们推荐使用组合而不是继承来重用组件之间的代码。 + +在这一章节中,我们将思考一些React新手通常遇到的问题,并展示如何使用组合来解决它们。 + +## 容器 + +一些组件并不能提前知道它们的子集。这在通用盒子组件,如 `Sidebar` 或者 `Dialog` 上尤其常见。 + +我们推荐这类组件使用特定的 `children` 属性,将子元素传递到其输出中: + +```js{4} +function FancyBorder(props) { + return ( +
+ {props.children} +
+ ); +} +``` + +这允许其他组件通过嵌套JSX传递任意的子集到组件内部: + +```js{4-9} +function WelcomeDialog() { + return ( + +

+ Welcome +

+

+ Thank you for visiting our spacecraft! +

+
+ ); +} +``` + +[Try it on CodePen.](http://codepen.io/gaearon/pen/ozqNOV?editors=0010) + +任何JSX标签 `` 内部的内容,都会作为 `children` 属性传递给 `FancyBorder` 组件。由于 `FancyBorder` 会在 `
` 中渲染 `{props.children}`,传递的元素将会出现在最终输出中。 + +虽然这不太常见,但有时您可能需要在组件中设置多个“孔”(holes,译者注:插槽)。在这种情况下,您可以采用您自己的约定,而不是使用 `children`: + +```js{5,8,18,21} +function SplitPane(props) { + return ( +
+
+ {props.left} +
+
+ {props.right} +
+
+ ); +} + +function App() { + return ( + + } + right={ + + } /> + ); +} +``` + +[Try it on CodePen.](http://codepen.io/gaearon/pen/gwZOJp?editors=0010) + +像 `` 和 `` 这样的React元素只是对象,所以你可以像传递其他数据一样将其作为属性传递。 + +## 具象化 + +有时我们认为某些组件是其他组件的“特殊情况”。比如,我们认为 `WelcomeDialog` 是一个特殊的 `Dialog`。 + +在React中,这也可以通过组合来实现,其中更“特殊”的组件会渲染更“通用”的组件,并且使用属性来配置通用组件: + +```js{5,8,16-18} +function Dialog(props) { + return ( + +

+ {props.title} +

+

+ {props.message} +

+
+ ); +} + +function WelcomeDialog() { + return ( + + ); +} +``` + +[Try it on CodePen.](http://codepen.io/gaearon/pen/kkEaOZ?editors=0010) + +组合对应定义为类的组件同样适用: + +```js{10,27-31} +function Dialog(props) { + return ( + +

+ {props.title} +

+

+ {props.message} +

+ {props.children} +
+ ); +} + +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 ( + + + + + ); + } + + handleChange(e) { + this.setState({login: e.target.value}); + } + + handleSignUp() { + alert(`Welcome aboard, ${this.state.login}!`); + } +} +``` + +[Try it on CodePen.](http://codepen.io/gaearon/pen/gwZbYa?editors=0010) + +## 那么继承呢? + +在Facebook,我们在数以千计的组件中使用React,并且我们没有发现任何用例会要求我们创建组件继承层次结构。 + +当你需要用安全的方式定制组件的外观和形式时,属性和组合给了你所有的灵活性。 请记住,组件接受任意props,包括原始值、React元素或函数。 + +如果你想在组件之中重用非UI的功能,我们建议您将其提取到单独的 `JavaScript` 模块中。组件可以导入它,并在不扩展它的情况下,使用哪些函数,对象或者是类。 \ No newline at end of file